升序排列列表中的列表,然后再降序排列。

54
如果我有一个包含如下列表的列表
['a',1] ['a',2] ['a',3] ['b',1] ['b',2] ['b',3]

如何对它们进行排序,使得第0个元素按降序排序,第1个元素按升序排序,从而实现以下结果

['b',1] ['b',2] ['b',3] ['a',1] ['a',2] ['a',3]

使用itemgetter可以在元素0上反向传递,但是我接下来要对元素进行排序时,它破坏了先前的排序。我不能使用组合键,因为它需要先按降序排序,然后按升序排序。


请在此处查看更多详细信息 https://dev59.com/MloU5IYBdhLWcg3wM1G9#37693603 - Venkat Ramana
3个回答

69
L = [['a',1], ['a',2], ['a',3], ['b',1], ['b',2], ['b',3]]
L.sort(key=lambda k: (k[0], -k[1]), reverse=True)

L现在包含:

[['b', 1], ['b', 2], ['b', 3], ['a', 1], ['a', 2], ['a', 3]]

会尽快接受。这正是我所需要的。我正在解决我们仓库拣货单中的垃圾箱位置/仓库路由问题,这个方法很有效。如果您有时间,能否解释一下“lambda k: (k[0],-k[1])”是什么意思?负号是否表示反转?如果没有反转参数,我可以使用“lambda k: (-k[0], k[1])”获得相同的结果吗? - Ominus
3
@Ominus说:-k[1]会将整数的符号翻转,以反转它们的自然排序顺序。你无法对字符串使用-k[0],所以reverse=True会反转排序顺序,而-k[1]会取消第二个元素上的这种反转。 - Steven Rumbalski

50

由于Python的sort稳定的,所以你可以进行连续的排序。但你需要首先对辅助键进行排序。您还可以参考官方HOW TO

from operator import itemgetter
l = [['a',2], ['a',1], ['b', 2], ['a',3], ['b',1], ['b',3]]
l.sort(key=itemgetter(1))
l.sort(key=itemgetter(0), reverse=True)
# [['b', 1], ['b', 2], ['b', 3], ['a', 1], ['a', 2], ['a', 3]]

4
如果第二个排序键没有相反的对立面(比如时间、字符串等),那么这将是一个可行的方法,因为在这种情况下无法使用已接受的答案。 - Thierry Lathuille

4

类似这样的内容

def mycmp(a, b):

  res = cmp(a[0], b[0])
  if res == 0:
     return cmp(a[1], b[1])
  return res

newlist = sorted(input_list, cmp=mycmp)

比较方法首先检查每个元素的第一项。如果它们相等,它将检查每个元素的第二项。在mycmp()实现中返回值可以被取反以实现不同的排序行为。

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