为什么我的列表没有按预期排序?

dis*_*ame 3 python sorting

我有一个dict()调用twitter_users,它将TwitterUser对象保存为值.我希望这些对象按字段排序mentioned.但是,使用sorted()并不像我期望的那样有效.我提供了一个lambda函数,用于确定是否更频繁地提到用户a或用户b.

srt = sorted(twitter_users.values(), 
         cmp=(lambda a,b: 
              True if a.mentioned > b.mentioned else False))

for s in srt:
    print s.mentioned
Run Code Online (Sandbox Code Playgroud)

不幸的是,这不起作用,列表srt没有以任何方式排序.

我怎样才能做到这一点?

Mar*_*ers 10

cmp函数应返回的整数,0当相等时,1或当更高a应该来后b-1或更低,如果他们应该来以相反的顺序.

你,而不是返回FalseTrue.因为Python布尔类型是其子类int,所以这些对象具有值0并且1在解释为整数时.你永远不会回来-1,所以你混淆了排序算法; 你告诉它的顺序,a并且b要么总是"平等",要么总是a来到之前b.但排序算法有时会要求ab交换,在这种情况下,你给它提供了相互矛盾的信息!

请注意,你的表达相当冗长; True if a.mentioned > b.mentioned else False可以简化为a.mentioned > b.mentioned; 在>操作者已经或者产生TrueFalse.使用简单的整数,您可以看到这不会产生预期的结果:

>>> sorted([4, 2, 5, 3, 8], cmp=lambda a, b: a > b)
[4, 2, 5, 3, 8]
Run Code Online (Sandbox Code Playgroud)

实际上返回-1,01工作:

>>> sorted([4, 2, 5, 3, 8], cmp=lambda a, b: 1 if a > b else 0 if a == b else -1)
[2, 3, 4, 5, 8]
Run Code Online (Sandbox Code Playgroud)

或者代替这种冗长的表达,只需使用内置cmp()函数 ; 对于你的情况你会像这样使用:

srt = sorted(twitter_users.values(), cmp=lambda a, b: cmp(a.mentioned, b.mentioned)) 
Run Code Online (Sandbox Code Playgroud)

但是,你真的不应该使用cmp 在所有 ; 有一个更简单(更有效)的选择.只需使用该key函数,它只返回mentioned属性:

srt = sorted(twitter_users.values(), key=lambda v: v.mentioned) 
Run Code Online (Sandbox Code Playgroud)

key函数产生实际排序的值; 该函数用于产生Schwartzian变换.这种转换更有效,因为它只被称为O(n)次,而该cmp函数被称为O(n log n)次.

因为您只访问属性,所以lambda您可以使用operator.attrgetter()对象为您执行属性获取:

from operator import attrgetter

srt = sorted(twitter_users.values(), key=attrgetter('mentioned')) 
Run Code Online (Sandbox Code Playgroud)