2

我有一个包含字典的列表,例如

[{'x': 42}, {'x': 23, 'y': 5}]

并希望确保所有 dicts 具有相同的键,None如果键不存在于原始 dict 中。所以上面的列表应该变成

[{'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)

但尤其是前两行似乎有点笨拙。想法?

4

3 回答 3

6
>>> 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}]
于 2012-05-07T13:05:35.740 回答
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}]

我们从所有字典中的所有键中创建一个集合,然后我们循环遍历dicts 并使用它们没有的任何值进行更新。

using 的替代方法itertools.chain.from_iterable()是 do reduce(or_, [dict.keys() for dict in dicts]), using functools.reduce()(in 3.x, reduce()builtin in 2.x) and operator.or_,尽管我觉得这不太可读。

如果您想创建一个新列表,而不是更新旧列表,只需将 for 循环替换为:

newdicts = [{key: item.get(key, None) for key in keys} for item in dicts]
于 2012-05-07T12:59:08.493 回答
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}]
于 2012-05-07T13:06:26.057 回答