4

我正在尝试从最小到最大对(字符串)轮胎尺寸列表进行排序。

['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 嵌套混乱的情况下解决此问题?

4

7 回答 7

10

Python 有几个特性使这很容易做到。实际上,您可以在一个语句中完成所有操作:

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

接受每个x.split("/")值并制作一个字符串列表:

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

Usingmap(int, ...)给出一个整数列表:

[235, 40, 17]

reversed()扭转局面:

[17, 40, 235]

并将tuple()其转换为元组:

(17, 40, 235)

与其他类似的元组相比,它给出了您想要的排序顺序。

于 2012-12-27T07:19:18.963 回答
1

一种方法是使用以下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 英寸的轮胎可能太大而无法骑行:-)

于 2012-12-27T07:18:59.963 回答
1

使用 、 和 的组合str.splitreversed创建tuple与 一起使用的键函数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("/")])))

sorted 函数接受一个序列和一个 key 函数,并返回一个序列中的项目列表,该列表按 key 函数的返回值对列表中的每个项目进行排序。这个关键函数,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']
于 2012-12-27T07:31:54.370 回答
1

很多很好的答案。如果您这样做只是为了例如缘故或快速的一次性解析或家庭作业,那么它们都说明字符串处理/排序很好。但是,如果您真的要围绕轮胎管理构建一个真正的应用程序,我会考虑为您的轮胎制作一个真实的轮胎模型:

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 排序),那么方便的元组反向技巧将不再起作用。将“它是什么”与您将如何呈现(排序)分开会更好(IMO)。之后你可能会想到一些更聪明的事情来处理它们,而不仅仅是对它们进行排序。

于 2012-12-27T19:38:53.700 回答
0

如果/s 的位置是恒定的,请尝试:

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

http://ideone.com/M6X6pW

于 2012-12-27T07:22:35.240 回答
0
    python 3.2

    sorted(list1,key=lambda x:x[-2:])
于 2012-12-27T16:49:21.363 回答
0

这个 Q/A 为我提供了解决我自己问题的指示 - 添加让其他人知道。
具有这种格式的 *nix 目录列表: /home/0000/Maildir/<0-255>/<userdirs>

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

列表大小从 3000 到 250000 项不等。

我需要在第四个字段上使用数字排序对列表进行排序,在每个项目中用“/”分隔

sorted(a, key=lambda y: int(y.split("/")[4]))
于 2013-02-06T08:54:45.110 回答