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(, function compares two arbitrary
values and returns a negative number if a, b) comes before a, or a positive number if b comes after a, or zero if they are
considered equal:
b
>>> 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