How to sort tire sizes in python

I am trying to sort a list of tire sizes (rows) from smallest to largest.

['285/30/18', '285/30/19', '235/40/17', '315/25/19', '275/30/19'] 

should look like this:

 ['235/40/17', '285/30/18', '315/25/19' '275/30/19', '285/30/19'] 

I basically have to sort the lines, starting from the right, middle and then from the left.

What I still have (bubble sort):

 # this sorts the first numbers on the right. nums = list(ulst) for i in range(len(nums)): for j in range(i+1, len(nums)): if ulst[j].split('/')[2] < ulst[i].split('/')[2]: ulst[j], ulst[i] = ulst[i], ulst[j] 

Now I need to sort the middle without messing up the sorting on the right row, and then sort the left row ....

How can I solve this problem without creating a nested mess?

+4
source share
7 answers

Python has several functions that make this easy to do. In fact, you can do all this in one statement:

 sorted(nums, key=lambda x: tuple(reversed(list(map(int, x.split("/")))))) 

x.split("/") takes each value and makes a list of lines:

 ["235", "40", "17"] 

Using map(int, ...) gives a list of integers:

 [235, 40, 17] 

reversed() rotates like this:

 [17, 40, 235] 

and tuple() converts this to a tuple:

 (17, 40, 235) 

which compared to other similar tuples gives the sort order you want.

+11
source

One way is to create a sort key using the following value function, which takes into account the three fields in the correct order:

 def value(s): arr = s.split('/') return arr[2] * 100000 + arr[1] * 1000 + arr[0] ulst = ['285/30/18', '285/30/19', '235/40/17', '315/25/19', '275/30/19'] for i in range(len(ulst)): for j in range(i+1, len(ulst)): if value(ulst[j]) < value(ulst[i]): ulst[j], ulst[i] = ulst[i], ulst[j] print ulst 

The result of this, if desired:

 ['235/40/17', '285/30/18', '315/25/19', '275/30/19', '285/30/19'] 

This will work just fine provided your tire sizes are 3/2/2 digits as indicated, which is a pretty safe bet - I have never seen tires below 12 inches and one in 100 inches would probably be too big. to ride :-)

+1
source

Use the composition str.split , reversed and tuple to create a key function to use with sorted :

 sizes = ['285/30/18', '285/30/19', '235/40/17', '315/25/19', '275/30/19'] s = sorted(sizes, key=lambda z: tuple(reversed([int(i) for i in z.split("/")]))) 

A sorted function takes a sequence and a key function and returns a list of elements in the sequence, sorted by the return value of the key function for each element of the list. This key lambda z function first splits the element into a "/" character to provide a list of strings, which are then converted to numbers, which are then passed to the reversed function, which gives the iterator a reverse order of the accepted sequence (NOTE: this is not yet evaluated), and the function tuple evaluates the inverse iterator, turning it into a sequence that can be used for sorting.

Thus, a sequence of strings formatted as "a / b / c" will be returned sorted by (c, b, a). This leads to:

 >>> print s ['235/40/17', '285/30/18', '315/25/19', '275/30/19', '285/30/19'] 
+1
source

Lots of good answers. If you do this, for example, for the sake of or just once, or homework, then all of them illustrate the correct processing / sorting of strings. But if you are really creating a real tire management application, I would consider creating a real tire model for your tires:

 from ast import literal_eval from operator import attrgetter # Make a real object, because we can, and it easy, and a real object is almost always better than abusing literal types class Tire(object): def __init__(self, width = 0, profile = 0, radius = 0): #now we have meaningful names to our indexed fields self.width = width self.profile = profile self.radius = radius # let encapsulate the '{width}/{profile}/{radius}' string representation # as an attribute so we can access/set it like the "real" attributes @property def description(self): return '{}/{}/{}'.format(self.width, self.profile, self.radius) @description.setter def description(self, string): self.width, self.profile, self.radius = map(literal_eval, string.split('/')) #ast.literal_eval() is safer than just eval() # let make a class side instance creation method that can instantiate and set the description directly too @classmethod def fromDescription(me, descriptionString): newTire = me() newTire.description = descriptionString return newTire #your original sample input descriptions = ['285/30/18', '285/30/19', '235/40/17', '315/25/19', '275/30/19'] #now lets make some real tire objects from those tires = [Tire.fromDescription(each) for each in descriptions] #make sure they still print [print(each.description) for each in tires] print('original sort') [print(each.description) for each in sorted(tires, key = attrgetter('radius'))] print('reversed original sort') [print(each.description) for each in sorted(tires, key = attrgetter('radius'), reverse = True)] print('width sort') [print(each.description) for each in sorted(tires, key = attrgetter('width'), reverse = True)] print('radius>>width>>profile sort') [print(each.description) for each in sorted(tires, key = attrgetter('radius', 'width', 'profile'))] 

The value of this approach, I hope, is obvious at the end. We pay a higher price per front (in terms of code space) to restore bus objects. But as soon as we have, we can start to go crazy, sorting them in different ways. The presented algorithms initially perfectly cope with some assumptions that link the string representation and the desired sorting result. But if you need to change your sort output in accordance with the last line (sort by fields 3, 1, 2), then the convenient inverse trick in tuples will no longer work. It’s much better (IMO) to separate β€œwhat is it” from how you are going to represent it (sort it). And you might think of even smarter deals with them after that than just sorting them.

+1
source

If the positions are / constant, try:

 sorted(a, key=lambda x:x[-2:]+x[4:6]+x[:3]) 

http://ideone.com/M6X6pW

0
source
  python 3.2 sorted(list1,key=lambda x:x[-2:]) 
0
source

This Q / A gave me pointers to fix my own problem - adding to let others know. Having lists of * nix directories in this format: /home/0000/Maildir/<0-255>/<userdirs>

0000 is a four-digit unique provider name
<0-255> - range

List sizes range from 3,000 to 250,000 items.

I needed to sort my lists with a numeric type in the fourth field, separated by a "/" in each element

 sorted(a, key=lambda y: int(y.split("/")[4])) 
0
source

All Articles