为什么在Python中使用sorted函数进行多级排序会得到错误的答案?

3
这篇文章与如何在Python中按字典的值对字典列表进行排序?不同,我认为无法使用lambda sort解决该问题,因为应该在两个属性上进行排序,一个升序,另一个降序。

我认为答案应该是:

按第二列降序排列,按第三列升序排列

[1, 5, 7]
[2, 3, 4]
[3, 2, 2]
[1, 2, 3]
[4, 2, 9]
[3, 1, 9]

但是输出结果是:
[1, 5, 7]
[2, 3, 4]
[1, 2, 3]
**[3, 2, 2]**   i think it's wrong here
[4, 2, 9]
[3, 1, 9]

代码如下:
l=[
        [1,2,3],
        [2,3,4],
        [1,5,7],
        [3,1,9],
        [3,2,2],
        [4,2,9]
   ]

def printlist(l):
    for ll in l:
        print ll

def comp1(a,b):
    if a[1]<b[1]:
        return 1
    if a[1]==b[1]:
        return a[2]>b[2]
    else:
        return -1

l3=sorted(l,cmp=comp1)
printlist(l3)

那么为什么程序输出了错误的答案?

Edit1: 这里我选择使用cmp而不是key=itemgetter(2,3),因为可能会有更复杂的结构,无法使用itemgetter进行排序,只能使用cmp函数进行排序。


cmp 已经在 Python3 中被移除,原因是一切都可以通过使用 key 来完成,并且更加高效。 - Ashwini Chaudhary
2个回答

3
这应该就可以了:
>>> sorted(l, key= lambda x:(-x[1], x[2]))
[
    [1, 5, 7], 
    [2, 3, 4], 
    [3, 2, 2], 
    [1, 2, 3], 
    [4, 2, 9], 
    [3, 1, 9]
]

做得不错 :) 但是为什么使用 cmp 方法无法得出正确答案?代码中有错误吗? - crazyminer
@crazyminer 在Python中,False == 0,因此根据您的代码,[1,2,3]和[3,2,2]是相等的,并且由于Python的排序是稳定的排序,[1,2,3]被首先返回。 - Ashwini Chaudhary

1

您的comp1函数应该返回一个正整数或负整数:

http://docs.python.org/2.7/library/functions.html#sorted

cmp指定了一个自定义比较函数,该函数接受两个参数(可迭代元素),并返回一个负数、零或正数,具体取决于第一个参数是被认为小于、等于还是大于第二个参数:cmp=lambda x,y: cmp(x.lower(), y.lower())。默认值为None。

在下一行中,您将返回一个布尔值:

return a[2]>b[2]

根据官方文档:
布尔值是两个常量对象False和True。它们用于表示真值(尽管其他值也可以被认为是false或true)。在数字上下文中(例如当用作算术运算符的参数时),它们分别像整数0和1一样工作。
因此,False返回0而不是-1。请将其替换为
return a[2] - b[2]

并且你已经准备就绪。

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