我知道有很多与字典操作有关的帖子,但是我找不到特殊情况的解决方案。 我有字典的列表(重复的字典键具有相似或不同的值),我必须从该列表中创建一个新字典。 例如:
a = [{u'a': 1}, {u'a': 2}, {u'a': 1}, {u'b': 2}, {u'b': 1}, {u'c': 1}, {u'c': 1}]
我正在寻找的输出:
{'a': 2, 'b':2, 'c': 1}
因此,如您所见,我只希望列表中每个键有一个条目,并且该键的值将是所有值的最大值。希望它不要太混乱。 我有一个工作中的灵魂,但是我只是想检查一下是否有更多的pythonic答案(用更少的#of线或更好的方法) 这是我的工作解决方案:
d = {}
for i in a:
if not d.get(i.keys()[0]):
d.update(i)
elif d.get(i.keys()[0], 0) < i.values()[0]:
d.update(i)
print d
感谢您的光临。
答案 0 :(得分:2)
您可以对列表a
进行排序,以使类似的键成为组,并且最大的值位于最后。然后添加值,以使最后一个值是字典中剩余的值:
>>> a = [{u'a': 1}, {u'a': 2}, {u'a': 1}, {u'b': 2}, {u'b': 1}, {u'c': 1}, {u'c': 1}]
>>> {k:v for k,v in (x.items()[0] for x in sorted(a))}
{u'a': 2, u'c': 1, u'b': 2}
或者,替代语法:
>>> dict(x.items()[0] for x in sorted(a))
对于Python 2和3语法:
>>> {k:v for k,v in (sorted(list(x.items())[0] for x in a))}
{'a': 2, 'b': 2, 'c': 1}
>>> dict(sorted(list(x.items())[0] for x in a))
{'a': 2, 'b': 2, 'c': 1}
来自评论:这是怎么回事?
首先,让我们提出一个更具启发性的示例:
>>> a = [{u'a': -1}, {u'a': -11}, {u'a': -3}, {u'b': 0}, {u'b': 100}, {u'c': 3}, {u'c': 1}]
因此,这里的期望结果是键(对于在dict中或使用OrderedDict保持顺序的Python 3)将是i)一组排序值中的键,然后ii)将值解释为递增值中的数字。
所以请先尝试:
>>> sorted(list(x.items())[0] for x in a)
[('a', -11), ('a', -3), ('a', -1), ('b', 0), ('b', 100), ('c', 1), ('c', 3)]
将其分解:
sorted(list(x.items())[0] for x in a)
^ ^ comprehension of
^ a list of one element dicts
^ ^ ^ convert to a two element tuple
^ sort the tuple first by key, then by value
因此可以通过首先按键对元组进行排序,然后按值对元组进行排序。
这会导致使用groupby
的替代解决方案:
>>> from itertools import groupby
>>> for k,v in groupby(sorted(list(x.items())[0] for x in a), key=lambda t: t[0]):
... print(k, max(v))
...
a ('a', -1)
b ('b', 100)
c ('c', 3)
groupby
解决方案在内存上更加友好,因为它不会创建额外的列表。第一种解决方案可能会以较小的字典列表而更快,因为排序更容易(但您需要对其进行测试。)
在我给出的解决方案中,并不是必需,而是将密钥进行了分组(groupby
才能正常工作)。这也可以:
>>> sorted((list(x.items())[0] for x in a), key=lambda t: t[1])
[('a', -11), ('a', -3), ('a', -1), ('b', 0), ('c', 1), ('c', 3), ('b', 100)]
然后使用dict构造函数将其转换为dict
。回想一下,该列表包含(key, value)
的元组列表:
>>> dict(sorted((list(x.items())[0] for x in a), key=lambda t: t[1]))
{'a': -1, 'b': 100, 'c': 3}
答案 1 :(得分:1)
您可以这样做:
a = [{u'a': 1}, {u'a': 2}, {u'a': 1}, {u'b': 2}, {u'b': 1}, {u'c': 1}, {u'c': 1}]
result = {}
for di in a:
for key, value in di.items():
result[key] = max(value, result.get(key, value))
print(result)
输出
{'a': 2, 'c': 1, 'b': 2}
答案 2 :(得分:1)
您可以使用defaultdict
:
from collections import defaultdict
d = defaultdict(lambda: 0)
for val in a:
if d[val.keys()[0]] < val.values()[0]:
d[val.keys()[0]] = val.values()[0]
输出
{u'a': 2, u'b': 2, u'c': 1}
答案 3 :(得分:1)
如果给定密钥不在新字典中或其值低于原始值,则可以通过遍历所有字典并用其内容更新最终字典new_a
来实现。
a = [{u'a': 1}, {u'a': 2}, {u'a': 1}, {u'b': 2}, {u'b': 1}, {u'c': 1}, {u'c': 1}]
new_a = {}
for dict_ in a:
key, value = list(dict_.items())[0]
if key not in new_a or new_a[key] < value:
new_a[key] = value
print(new_a) # -> {'c': 1, 'b': 2, 'a': 2}