如何在python中对轮胎尺寸进行排序

问题描述:

我试图从(从最小到最大)轮胎尺寸列表(字符串)进行排序。如何在python中对轮胎尺寸进行排序

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

应该是排序为:

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

我基本都从右边开始的字符串进行排序,中间然后离开。

我有什么至今(冒泡排序):

# 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] 

我现在有排序没有搞乱右侧排排序的中间,然后进行排序左行....

如何在不创建for/if嵌套混乱的情况下解决此问题?

Python有几个功能,这使得这很容易做到。事实上,你可以做到这一切在一个声明:

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

x.split("/")需要每个值,使字符串列表:

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

使用map(int, ...)给出了一个整数列表:

[235, 40, 17] 

reversed()转过来:

[17, 40, 235] 

tuple()转换到这一个元组:

(17, 40, 235) 

其中,相比其他类似的元组的时候,给你想要的排序顺序。

+1

这强调了一个切点分隔的排序:它通常是好喜欢像'内置行为排序“,而不是实现你自己的排序功能。当然,除非你的目标是实现一个排序功能。 –

+0

'reversed()'实际上返回一个迭代器。 –

+0

@AshwiniChaudhary:谢谢,这提醒我检查一下,这在Python 3.x中有效。我不得不在'map()'和'reversed()'之间添加一个额外的'list()'。 'tuple()'很高兴能够迭代。 –

的一种方法是使用以下value函数,其考虑到构造排序键以正确的顺序的三个字段:

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 

的输出是,如所期望:

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

只要您的轮胎尺寸是指定的3/2/2位数,这是一个相当安全的赌注 - 我从未见过12英寸以下的轮胎和100英寸的其中一个可能会太大以至于无法骑行: - )

如果/ S的位置固定,尝试:

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

​​

使用str.splitreversedtuple组成创建密钥功能与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("/")]))) 

的排序函数接受一个序列和一个键函数,并返回按列表中每个项的键函数的返回值排序的序列的项目列表。此键的功能,lambda z,第一分割上“/”字符的项目,得到的字符串列表,然后将它们各自转换成数字,然后将其传递给reversed功能这给序列相反的顺序进行的一个迭代传入(注意:这还没有评估),并且tuple函数评估反向迭代器,将其转化为可用于排序的序列。

所以格式化像 “A/B/C” 串的序列将被返回排序方法(C,B,A)。这导致:

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

使用字符串比较而不是int比较是一个非常糟糕的主意:'“19” Voo

+0

当然你是对的。我编辑它来正确处理这个问题。谢谢。 – Misandrist

python 3.2 

    sorted(list1,key=lambda x:x[-2:]) 

很多好的答案。如果你只是为了例如清单或快速解析,或者作业分配,那么它们都会说明字符串处理/排序的好处。但是,如果你真的建立围绕轮胎管理真正的应用程序,我会考虑轮胎的实际模型,为您的轮胎:

from ast import literal_eval 
from operator import attrgetter 

# Make a real object, because we can, and it's 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's 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's 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'))] 

这种方法的价值是显而易见的希望在年底。我们在代码空间方面付出了更大的代价来确定轮胎对象。但是,一旦我们有了,我们可以开始坚持以各种方式对它们进行排序。本文提出的算法在给定的假设条件下将字符串表示和期望的排序输出结合起来,效果很好。但是如果你需要改变你的排序输出,按照最后一行(按照字段3,1,2排序),那么元组的方便逆向技巧将不再适用。 (“国际海事组织”)将“它是什么”与你如何呈现(分类)分开是好得多的。而且,你可能会想到甚至更聪明的事情,而不仅仅是对它们进行排序。

+0

它实际上是一个小型的Django应用程序。我现在知道排序特定数据集合的最佳方法,下一步实际上是在models.py中实现它,或者可能按请求对它进行排序,并将排序后的数据作为序列化的json集合返回。这是一个很好的开始,感谢您的意见。 – davierc

这个Q/A给了我解决我自己的问题的指针 - 增加让别人知道。
具有这种格式的* nix的目录列表: /home/0000/Maildir/<0-255>/<userdirs>

0000 - 四位数的唯一供应商名称
< 0-255> - 范围

名单大小变化从3000 250000项。

我需要我的名单上的第四场数字排序,由“/”中的每个项目

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