我有一个包含
等字典的列表[{'x': 42}, {'x': 23, 'y': 5}]
并希望确保所有dicts具有相同的键,如果原始字典中没有键,则值为None
。所以上面的列表应该成为
[{'x': 42, 'y': None}, {'x': 23, 'y': 5}]
最美丽和最蟒蛇的方法是什么?目前的做法:
keys = reduce(lambda k, l: k.union(set(l)), [d.keys() for d in my_list], set())
new_list = [dict.fromkeys(keys, None) for i in xrange(len(my_list))]
for i, l in enumerate(my_list):
new_list[i].update(l)
但特别是前两行似乎有些笨拙。想法?
答案 0 :(得分:5)
>>> from itertools import chain
>>> l = [{'x': 42}, {'x': 23, 'y': 5}]
>>> all_keys = set(chain.from_iterable(l))
>>> for d in l:
d.update((k,None) for k in all_keys-d.viewkeys())
>>> l
[{'y': None, 'x': 42}, {'y': 5, 'x': 23}]
答案 1 :(得分:3)
最简单的方法:
from itertools import chain
dicts = [{'x': 42}, {'x': 23, 'y': 5}]
keys = set(chain.from_iterable(dicts))
for item in dicts:
item.update({key: None for key in keys if key not in item})
给我们:
[{'y': None, 'x': 42}, {'y': 5, 'x': 23}]
我们从所有词典中的所有键创建一个集合,然后我们使用他们没有的任何值循环dict
s更新。
使用itertools.chain.from_iterable()
的替代方法是reduce(or_, [dict.keys() for dict in dicts])
,使用functools.reduce()
(在3.x中,在2.x中内置reduce()
)和{{ 1}},虽然我觉得这不太可读。
如果您想创建一个新列表,而不是更新旧列表,只需将for循环替换为:
operator.or_
答案 2 :(得分:2)
这将创建一个新的词典列表,所有词典都包含完整的键:
>>> import itertools as it
>>> l = [{'x': 42}, {'x': 23, 'y': 5}]
>>> all_keys = set(it.chain.from_iterable(l))
>>> [dict((k, a.get(k, None)) for k in all_keys) for a in l]
[{'x': 42, 'y': None}, {'x': 23, 'y': 5}]