Next / Previous / Contents / TCC Help System / NM Tech homepage

11.4. Snail-oriented data structures: A list of tuples

To improve on the script above, let's modify the script so that it keeps each snail's time and name together in a two-element tuple such as (87.3, 'Judy').

In the improved script, the timeList list is a list of these tuples, and not just a list of times. We can then sort this list, using an interesting property of tuples. If you compare two tuples, and their first elements are not equal, the result is the same as if you compared their first elements. However, if the first elements are equal, Python then compares the second elements of each tuple, and so on until it either finds two unequal values, or finds that all the elements are equal.

Here's an example. Recall that the function cmp(a, b), function compares two arbitrary values and returns a negative number if a comes before b, or a positive number if a comes after b, or zero if they are considered equal:

>>> cmp(50,30)
1
>>> cmp(30,50)
-1
>>> cmp(50,50)
0
>>> 

If you compare two tuples and the first elements are unequal, the result is the same as if you compared the first two elements. For example:

>>> cmp ( (50,30,30), (80,10,10) )
-1
>>> 

If, however, the first elements are equal, Python then compares the second elements, or the third elements, until it either finds two unequal elements, or finds that all the elements are equal:

>>> cmp ( (50,30,30), (80,10,10) )
-1
>>> cmp ( (50,30,30), (50,10,10) )
1
>>> cmp ( (50,30,30), (50,30,80) )
-1
>>> cmp ( (50,30,30), (50,30,30) )
0
>>> 

So, watch what happens when we sort a list of two-tuples containing snail times and names:

>>> timeList = [ (87.3, 'Judy'), (96.6, 'Kyle'), (63.0, 'Lois') ]
>>> timeList.sort()
>>> timeList
[(63.0, 'Lois'), (87.299999999999997, 'Judy'), (96.599999999999994, 'Kyle')]
>>> 

Now we have a list that is ordered the way the snails finished. Here is our modified script:

#!/usr/local/bin/python
#================================================================
# snailtuples.py:  Second snail racing results script.
#----------------------------------------------------------------

#--
# Create an empty list to hold the result tuples.
#--
timeList = []

#--
# Open the file containing the results.
#--
resultsFile = open ( 'results' )

#--
# Go through the lines of that file, storing each finish time.
# Note that 'resultsLine' is set to each line of the file in
# turn, including the terminating newline ('\n').
#--
for  resultsLine in resultsFile:
    #--
    # Create a list of the fields in the line, e.g., ['87.3', 'Judy\n'].
    # We use the second argument to .split() to limit the number
    # of fields to two maximum; the first argument (None) means
    # split the line wherever there is any whitespace.
    #--
    fieldList  =  resultsLine.split(None, 1)

    #--
    # Now create a tuple (time,name) and append it to fieldList.
    # Use .rstrip to remove the newline from the second field.
    #--
    snailTuple = (float(fieldList[0]), fieldList[1].rstrip())
    timeList.append ( snailTuple )

#--
# Sort timeList into ascending order.
#--
timeList.sort()

#--
# Print the results.
#--
print "Finish  Time  Name"
print "------ ------ ----"
for  position in range(len(timeList)):
    snailTuple  =  timeList[position]
    print "{0:4d}   {1:6.1f} {2}".format(position+1, snailTuple[0],
                                         snailTuple[1])

Here is a sample run with our original two-snail results file:

Finish  Time  Name
------ ------ ----
   1     87.3 Judy
   2     96.6 Kyle

Let's try a larger results file with some names that have spaces in them, just to exercise the script. Here's the input file:

93.3 Queen Elizabeth I
138.4 Erasmus
88.2 Jim Ryun

And the output for this run:

Finish  Time  Name
------ ------ ----
   1     88.2 Jim Ryun
   2     93.3 Queen Elizabeth I
   3    138.4 Erasmus