python字典值排序
我有两个字典,python字典值排序,python,sorting,dictionary,Python,Sorting,Dictionary,我有两个字典,dict1和dict2,它们包含相同的键,但键的值不同。我要做的是对每个字典,从最大值到最小值排序,然后给每个值一个秩1-N,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,
dict1
和dict2
,它们包含相同的键,但键的值不同。我要做的是对每个字典,从最大值到最小值排序,然后给每个值一个秩1-N,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
我知道字典应该是随机的,不可排序的,但也许有一种方法可以将键和值放入列表中?我面临的主要挑战是获取按值(从大到小)排序的键和值,然后将值更改为排序列表中的相应等级 您可能对
这是一个示例,我最初的想法是,您也在寻找键按值排序的字典,od1
和od2
是
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是他的第二个更高效的版本):
如果有人想发布格式化的更大的dicts,我也会测试它们。您使用的是什么版本的python?如果是2.7,请使用OrderedDict 根据Python 2.7: 如果您使用的是Python2.4-2.6,您仍然可以通过从pypi安装OrderedDict来使用它,或者如果您已经安装了OrderedDict,请运行
对于小型dict,一个简单的解决方案是
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)
更高效、可读性更低的版本,适用于更大的DICT:
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)
字典不是解决这个问题的正确数据结构。您应该尽快转换为已排序的列表,并仅生成字典作为最终结果。以下示例解决方案尽可能使用迭代器和生成器表达式,以避免在过程中创建过多(可能较大)的帮助器列表:
def get_ranking(vals):
'''Return a list of pairs: (key, ranking), sorted by key.'''
ranking = sorted(((v, k) for k, v in vals.iteritems()), reverse=True)
return sorted((k, i) for (i, (_v, k)) in enumerate(ranking))
def ranking_diff(rank1, rank2):
return dict((k, v1 - v2) for (k, v1), (_, v2) in itertools.izip(rank1, rank2))
def get_diffs(dict1, dict2):
r1 = get_ranking(dict1)
r2 = get_ranking(dict2)
return ranking_diff(r1, r2)
print get_diffs(dict1, dict2)
# prints: {'a': -2, 'c': 1, 'b': 2, 'e': 1, 'd': -2}
请注意,此解决方案假定两个DICT包含完全相同的密钥。同意!特别是因为我们的两个答案都是完全有效的解决方案。我也投了你的一票,以否定做这件事的人的行为。我没有投反对票,但我认为,
OrderedDict
在这里没有任何帮助。要实现OP想要的功能,实际上不需要对字典进行排序。此外,你给出的关键功能是错误的。哦,该死,你对关键功能的看法是正确的。我只是直接从文档中复制/粘贴。。。将编辑。+1。没有多少人用这种方式使用map
和reversed
。棘手:-)但我建议使用itertools.imap
来节省一些内存。同意。通常,出于性能原因,我建议使用列表理解或生成器表达式而不是map(直到现在才知道imap),但我认为这是一个更好、更可读的解决方案。Kudos:-)不会更快排序(dict1.items(),key=lambda item:item[1])因为这样你就不需要在字典中查找每一个值了?@Aleksi:首先,字典查找相当快。我认为sorted(dict1,key=dict1.get)
更快,因为您没有为每个项目调用Python函数的开销。当然,表达式可以写成排序的(dict1.items(),key=operator.itermgetter(1)),从而消除lambda函数并使此参数无效。但是第二,您的表达式返回的列表与我的不同。我需要以某种方式去除这些值。@Sven:是的,我想在enumerate(排序的(dict1.items(),key=operator.itemgetter(1))中的dict((key,rank)for rank,(key,value))行中做一些事情,但是如果列表理解比map
+倒转的,我的观点确实没有意义。这是一个错误的工作工具,询问者并不需要一个有序的字典,Asker说:我面临的主要挑战是获得按值排序的键和值,在我看来,orderedict
似乎是正确的工具。我看不出orderedict
如何简化生成diff
字典的任务。你能举个完整的例子吗?(顺便说一句,不是我的反对票。)是的,但看看问题。首先您有字典,然后您需要获得值的排序(对于这些值,您不需要有序字典),然后您需要在最终的字典中获得排序结果。你在任何地方都不需要有序的词典,它们是完成这项工作的错误工具。例如,看看斯文斯的答案。
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)
def get_ranking(vals):
'''Return a list of pairs: (key, ranking), sorted by key.'''
ranking = sorted(((v, k) for k, v in vals.iteritems()), reverse=True)
return sorted((k, i) for (i, (_v, k)) in enumerate(ranking))
def ranking_diff(rank1, rank2):
return dict((k, v1 - v2) for (k, v1), (_, v2) in itertools.izip(rank1, rank2))
def get_diffs(dict1, dict2):
r1 = get_ranking(dict1)
r2 = get_ranking(dict2)
return ranking_diff(r1, r2)
print get_diffs(dict1, dict2)
# prints: {'a': -2, 'c': 1, 'b': 2, 'e': 1, 'd': -2}