3

是否有更pythonic,更快的希望按值对字典进行排名并对非唯一值的排名进行平均。我的做法:

d = {'a':5,'b':5,'c':5,'d':1,'e':6}
ordered_keys = sorted(d, key=d.get)
ordered_v = [d[k] for k in ordered_keys]
value_rank = [(ordered_v.index(v)+1)+(ordered_v.count(v)-1)/2 for v in ordered_v]
ranked_key_list = zip(ordered_keys,value_rank)
[('d', 1), ('a', 3), ('c', 3), ('b', 3), ('e', 5)]

这个关于排序字典的广泛讨论非常有帮助:python 字典值排序

4

3 回答 3

3

你所拥有的非常好,我怀疑有一个更短的解决方案。

至于效率,重复使用list.index()andlist.count()可能会减慢大型数据集的速度。

如果您对大量数据执行此操作,则这是一种更有效的替代实现:

from itertools import groupby

d = {'a':5,'b':5,'c':5,'d':1,'e':6}
ranked_key_list = []
i = 1
for k, g in groupby(sorted(d.keys(), key=d.get), key=d.get):
    g = list(g)
    rank = i + (len(g)-1) / 2
    ranked_key_list.extend((k, rank) for k in g)
    i += len(g)
于 2012-12-07T21:14:22.847 回答
3

你的算法的瓶颈是 .index 和 .count 是 O(n),因此你的瓶颈是这条线:

value_rank = [(ordered_v.index(v)+1)+(ordered_v.count(v)-1)/2 for v in ordered_v]

导致您的整体表现为 O(n^2)

我为你做了一个 O(n*log(n)) 算法(瓶颈现在是排序):

import collections

d = {'a':5,'b':5,'c':5,'d':1,'e':6}
my_d = collections.defaultdict(list)
for key, val in d.items():
    my_d[val].append(key)

ranked_key_list = [] 
n = v = 1
for _, my_list in sorted(my_d.items()):
    v = n + (len(my_list)-1)/2 
    for e in my_list:
        n += 1
        ranked_key_list.append((e, v))
于 2012-12-07T21:40:49.193 回答
0
key_list = zip(dict.keys(), dict.values())
ranked_key_list = sorted(key_list, key=lambda x: x[1])

编辑:刚刚意识到我没有做平均值的事情......你能再澄清一点吗?3 5s = 3的平均值是多少?

于 2012-12-07T20:35:04.590 回答