Python如何对元组列表进行排序?

72

经实践发现,当Python的默认列表排序器收到一个由元组组成的列表时,它会按照每个元组中第一个元素的大小进行排序。这个说法正确吗?如果不是,那么按照元组的第一个元素对列表进行排序的正确方法是什么?

5个回答

88

它自动按照元组中的第一个元素排序,然后按照第二个元素依此类推进行排序。因此,tuple([1,2,3])将在tuple([1,2,4])之前。如果要覆盖此行为,请将可调用对象作为sort方法的第二个参数传递。该可调用对象应返回1、-1或0。


17
如果使用sort的key参数就不要使用cmp参数!因此,最好使用foo.sort(key=lambda x: x[1])而不是foo.sort(lambda x, y: cmp(x[1], y[1]))。这样更易于理解并且更有效率。 - cthulahoops
10
我认为在这种情况下使用operator.itemgetter要比lambda函数更好: foo.sort(key=operator.itemgetter(1))foo.sort(key=lambda x: x[1]) 更加简洁。不过这只是我的观点。 - Jarek Przygódzki
3
不过,如果有相关文档的链接会更好。 - user4385532
虽然有些晚了几年,但这是来自相关文档的内容:“...元组按字典顺序进行比较;首先比较第一个元素;如果它们相同,则比较第二个元素,依此类推。” - undefined

10
是的,这是默认设置。事实上,这是Python中经典的“DSU”(装饰-排序-去装饰)习语的基础。请参阅《像Pythonista一样编码》。

1
10年后,链接已失效。这是文章吗?页面25。 - alex

9
不,元组与字符串一样是序列类型。它们按照相同的方式排序,通过逐个比较每个元素来实现:
>>> import random
>>> sorted([(0,0,0,int(random.getrandbits(4))) for x in xrange(10)])
[(0, 0, 0, 0), (0, 0, 0, 4), (0, 0, 0, 5), (0, 0, 0, 7), (0, 0, 0, 8),
(0, 0, 0, 9), (0, 0, 0, 12), (0, 0, 0, 12), (0, 0, 0, 12), (0, 0, 0, 14)]

这三个零只是为了表示必须检查除第一个元素以外的其他内容。

嗯,我似乎是少数派……如果Python只通过查看每个元组中的第一个元素进行排序,我就无法理解我的测试结果。 - unwind
它从第一项开始,然后继续执行。请参考Vasil的答案。 - Hartley Brody

0
尝试使用内部列表排序方法并传递lambda函数。如果您的元组第一个元素是整数,那么这应该可以工作。
# l is the list of tuples
l.sort(lambda x,y: x-y)

您可以使用任何可调用的函数作为比较函数,不一定是lambda表达式。但是它需要返回-1(小于),0(等于)或1(大于)。


这个与元组列表怎么搭配使用呢?我遇到了TypeError: unsupported operand type(s) for -: 'tuple' and 'tuple'。 - S.Lott
在sort中执行的lambda函数必须有一个参数,该参数是元组序列的可迭代元素:pairs.sort(key=lambda pair: pair[1])。如果您想在按第一个元素排序后再进行第二层排序,则可以使用pairs.sort(key=lambda pair: (pair[1], pair[0]))。 - Alex

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接