1

I am working on a piece of Python code that consists of allowing the user to enter the top speed for 3 different cars, then prints out the car's name and top speed sorted in ascending order.

So far, two lists have been created

carName= ["Ferrari", "Lambo", "Porsche"]

and

carSpeed= ["245.5794", "242.4616", "318.1555"]

The carSpeed has been rounded to 2 decimal place with

carSpeedTwoDP= ['%.2f' % elem for elem in carSpeed]

And that list, along with carName, has been made into a tuple

carSpeedSorted= sorted(zip(carSpeed, carName))

I then print out the tuple with

for i in range (3):
    print "%s"% (carSpeedSorted[i],)

This poses a problem however. The table is supposed to show

Lambo 242.46
Ferrari 245.58
Porsche 318.16

But because the speed is first in the tuple (as the list must be sorted in ascending speed order and tuples sort themselves with the first elements they can find), the display is the following:

('242.46', 'Lambo')
('245.58', 'Ferrari')
('318.16', 'Porsche ')

I have been researching for a while, but haven't been able to come up with a solution to invert the lists so that the car name shows up first, all the while keeping the tuple sorted by speed.

Any help would be greatly appreciated! Thank you!

Johny
  • 129
  • 11

6 Answers6

1

You can simply put the car names first and sort using the second element of each tuple as the key:

from operator import itemgetter
carSpeedSorted = sorted(zip(carName, carSpeed), key=itemgetter(1))

And now:

for a in carSpeedSorted:
    print '%s' % (a,) 
('Lambo', '242.4616')
('Ferrari', '245.5794')
('Porsche', '318.1555')

References:

arshajii
  • 127,459
  • 24
  • 238
  • 287
1

What happened to the reversed slice operator?

print (0, 1, 2)[::-1]
# Outputs '(2, 1, 0)'

This is known as 'Reverse Slicing'. It's minimal, but it works in anything that is pretty much a sequence, or contains multiples of an item, such as a tuple or a list. You can read more about reversal here.

Community
  • 1
  • 1
Zizouz212
  • 4,908
  • 5
  • 42
  • 66
1

There are two solutions to your problem.

1. Fix printing

There are ways to do that:

carSpeedSorted[i] = ('242.46', 'Lambo')

print "{1} {0}".format(*carSpeedSorted[i])

# or:
print "%s %s" % (carSpeedSorted[i][1], carSpeedSorted[i][0])

# or:
speed, name = carSpeedSorted[i]
print "%s %s" % (name, speed)

# or:
print "%(name)s %(speed)s" % dict(speed=carSpeedSorted[i][0], 
                                  name=carSpeedSorted[i][1])

2. Fix sorting

You can have (name, speed) tuples and still sort by speed, e.g.:

sorted(name_speed_tuples, key=lambda name_speed: name_speed[1])

BTW, are sure you want to sort by speed alphabeticaly?

In your code, speed '1000.00' will come before '200.00'!

I suggest using round for rounding the numbers, instead of creating a string. That would fix the problem.

carSpeedTwoDP= [round(elem,2) for elem in carSpeed]
zvone
  • 18,045
  • 3
  • 49
  • 77
0

Actually you can very easily sort by second elements of tuples:

sorted(zip(carName, carSpeed), key=lambda x: (x[1], x[0]))

The above method sorts the list of tuples in ascending order of their speeds, and in case of a draw, the one with smaller name comes first.

pkacprzak
  • 5,537
  • 1
  • 17
  • 37
0

Why not just print it in the required order?

print( "%s %s" %(carSpeedSorted[i][1],carSpeedSorted[i][0]))

OUTPUT

Lambo 242.4616
Ferrari 245.5794
Porsche 318.1555
astrosyam
  • 857
  • 4
  • 15
0

Others correctly point out that you can sort without reversing the items in the first place, but if you want to print when the tuple is in the "wrong" order, it's not hard, just reverse the tuple (and make the format string print both parts):

# Iterate list directly; indexing on range is a C habit you should get out of
for carspeed in carSpeedSorted:
    # Reverse the tuple and use it directly; wrapping in a single element
    # tuple adds the parens and commas your desired output didn't want
    print "%s %s" % carspeed[::-1]
ShadowRanger
  • 143,180
  • 12
  • 188
  • 271