Python字典值排序

9 投票
4 回答
12962 浏览
提问于 2025-04-16 17:53

我有两个字典,dict1dict2,它们的键是一样的,但每个键对应的值不同。我想做的是,先把每个字典里的值从大到小排序,然后给每个值一个排名,1代表最大值。接着,我想比较这两个字典中同一个键的值的排名差异。例如:

dict1 = {a:0.6, b:0.3, c:0.9, d:1.2, e:0.2}
dict2 = {a:1.4, b:7.7, c:9.0, d:2.5, e:2.0}

# sorting by values would look like this:
dict1 = {d:1.2, c:0.9, a:0.6, b:0.3, e:0.2}
dict2 = {c:9.0, b:7.7, d:2.5, e:2.0, a:1.4}

#ranking the values would produce this:
dict1 = {d:1, c:2, a:3, b:4, e:5}
dict2 = {c:1, b:2, d:3, e:4, a:5}

#computing the difference between ranks would be something like this:
diffs = {}
for x in dict1.keys():
    diffs[x] = (dict1[x] - dict2[x])

#diffs would look like this:
diffs[a] = -2
diffs[b] = 2
diffs[c] = 1
diffs[d] = -2
diffs[e] = 1

我知道字典本身是随机的,不能直接排序,但也许可以把键和值放到一个列表里?我面临的主要挑战是如何根据值进行排序(从大到小),然后把值改成在排序列表中的相应排名。

4 个回答

2

你正在使用哪个版本的Python?如果是2.7版本,建议使用OrderedDict。

根据Python 2.7的文档

OrderedDict(sorted(d.items(), key=d.get))

如果你使用的是Python 2.4到2.6版本,你仍然可以通过从pypi安装OrderedDict,点击这里,或者如果你已经安装了setuptools,可以运行

easy_install ordereddict
6

你可能会对 collections.OrderedDict 感兴趣。

这里有个例子,我最开始的想法是你可能也在寻找按值排序的字典,像 od1od2 这样的。

d1 = {"a":0.6, "b":0.3, "c":0.9, "d":1.2, "e":0.2}
d2 = {"a":1.4, "b":7.7, "c":9.0, "d":2.5, "e":2.0}

od1 = OrderedDict(sorted(d1.items(), key=lambda t: t[1]))
od2 = OrderedDict(sorted(d2.items(), key=lambda t: t[1]))

k1 = od1.keys()
k2 = od2.keys()

diff = dict((k, n - k2.index(k)) for n, k in enumerate(k1))

如果你不需要这些功能,那么Sven的解决方案可能会更快。

编辑:其实也没快多少……(sven.py是他第二个更高效的版本):

$ cat /tmp/mine.py | time python -m timeit
10000000 loops, best of 3: 0.0842 usec per loop
real    0m 3.69s
user    0m 3.38s
sys 0m 0.03s
$ cat /tmp/sven.py | time python -m timeit
10000000 loops, best of 3: 0.085 usec per loop
real    0m 3.86s
user    0m 3.42s
sys 0m 0.03s

如果有人想发布格式化的更大字典,我也会测试它们。

8

对于小字典,一个简单的解决方案是:

dict1 = {"a":0.6, "b":0.3, "c":0.9, "d":1.2, "e":0.2}
dict2 = {"a":1.4, "b":7.7, "c":9.0, "d":2.5, "e":2.0}
k1 = sorted(dict1, key=dict1.get)
k2 = sorted(dict2, key=dict2.get)
diffs = dict((k, k2.index(k) - k1.index(k)) for k in dict1)

而对于较大的字典,有一个更高效但可读性较差的版本:

ranks1 = dict(map(reversed, enumerate(sorted(dict1, key=dict1.get))))
ranks2 = dict(map(reversed, enumerate(sorted(dict2, key=dict2.get))))
diffs = dict((k, ranks2[k] - ranks1[k]) for k in dict1)

撰写回答