python,按字符而不是键将字典转换为排序列表

时间:2009-12-16 15:54:15

标签: python sorting

我有一个collections.defaultdict(int),我正在构建它来计算一个键出现在一组数据中的次数。我后来希望能够以递减的方式对它进行排序(显然首先将其转换为列表),先按最高值排序。我创建了如下字典:

adict = defaultdict(int)

稍后我会做一堆:

adict['someval'] += 1
adict['anotherval'] +=1
adict['someval'] += 1

理想情况下,我想要打印出来:

someval => 2
anotherval => 1

7 个答案:

答案 0 :(得分:42)

要对字典进行排序:

from operator import itemgetter

sorted(adict.iteritems(), key=itemgetter(1), reverse=True)

答案 1 :(得分:36)

dict的键,按相应的值反向排序,最好是

sorted(adict, key=adict.get, reverse=True)

因为你想要键/值对,你可以像所有其他答案所建议的那样处理这些项目,或者(使用漂亮的adict.get绑定方法而不是项目符号或怪异的lambdas; - ),

[(k, adict[k]) for k in sorted(adict, key=adict.get, reverse=True)]

修改:就性能而言,无论如何都没有多少内容:

$ python -mtimeit -s'adict=dict((x,x**2) for x in range(-5,6))' '[(k, adict[k]) for k in sorted(adict, key=adict.get, reverse=True)]'
100000 loops, best of 3: 10.8 usec per loop
$ python -mtimeit -s'adict=dict((x,x**2) for x in range(-5,6)); from operator import itemgetter' 'sorted(adict.iteritems(), key=itemgetter(1), reverse=True)'
100000 loops, best of 3: 9.66 usec per loop
$ python -mtimeit -s'adict=dict((x,x**2) for x in range(-5,6))' 'sorted(adict.iteritems(), key=lambda (k,v): v, reverse=True)'
100000 loops, best of 3: 11.5 usec per loop

因此,基于.get的解决方案在两个基于items的解决方案之间的性能中途 - 略慢于itemgetter,略快于lambda }。在“瓶颈”情况下,那些微秒级分对你来说至关重要,无论如何都要关注它。在正常情况下,这个操作只是在一个更大的任务中只有一步而且微秒或多或少的事情很少,但是,关注简单get成语也是一个合理的选择。

答案 2 :(得分:4)

只需按值对结果dict进行排序:

for k, v in sorted(adict.items(), key=lambda kv: kv[1], reverse=True):
    print("%s => %s" % (k,v))

答案 3 :(得分:3)

注意:我把它作为一个答案,以便它被看到。我不想要upvotes。如果你想赞助任何人,请赞成Nadia。

当前接受的答案提供的计时结果基于一个简单的小数据集(size == 6 - (-5)== 11)。开销掩盖了各种方法的成本差异。用例如文本中最常用的单词或成员列表或人口普查中最常见的名称涉及更大的数据集。

使用范围(-n,n + 1)重复实验(Windows框,Python 2.6.4,所有时间都以微秒为单位):

n = 5:11.5,9.34,11.3
n = 50:65.5,46.2,68.1
n = 500:612,423,614

这些结果并非“略有”不同。 项目回答是速度明显的赢家。

还提到了“ get成语的简单性”。将它们放在一起以便于比较:

[(k, adict[k]) for k in sorted(adict, key=adict.get, reverse=True)] sorted(adict.iteritems(), key=itemgetter(1), reverse=True)

get成语不仅两次查找字典(如J. F. Sebastian指出的那样),它使一个列表(sorted()的结果)然后迭代该列表以创建结果列表。我称之为巴洛克式,而非简单。 YMMV。

答案 4 :(得分:2)

from collections import defaultdict
adict = defaultdict(int)

adict['a'] += 1
adict['b'] += 3
adict['c'] += 5
adict['d'] += 2

for key, value in sorted(adict.items(), lambda a, b: cmp(a[1], b[1]), reverse=True):
    print "%r => %r" % (key, value)

>>> 
'c' => 5
'b' => 3
'd' => 2
'a' => 1

答案 5 :(得分:2)

如果您使用的是最新的python 2.7 alpha,那么您可以在集合模块中使用Counter类:

c = Counter()

c['someval'] += 1
c['anotherval'] += 1
c['someval'] += 1

print c.most_common()

以正确的顺序打印:

[('someval', 2), ('anotherval', 1)]

2.7上使用的代码是available already,而且版本为adapted to 2.5。也许您希望使用它来保持与即将发布的本机stdlib版本的前向兼容。

答案 6 :(得分:0)

“反转”字典。

from collections import defaultdict
inv_dict = defaultdict( list )
for key, value in adict:
    inv_dict[value].append( key )
max_value= max( inv_dict.keys() )

具有最大出现次数的键集 -

inv_dict[max_value] 

按出现次数降序排列的键 -

for value, key_list in sorted( inv_dict ):
    print key_list, value