2

私は次のような辞書のリストを持っています

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

Noneそして、すべてのdictが同じキーを持ち、キーが元のdictに存在しなかったかどうかの値を持っていることを確認したい。したがって、上記のリストは次のようになります。

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

これを行うための最も美しく、Pythonの方法は何ですか?現在のアプローチ:

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)

しかし、特に最初の2行はちょっと不器用に見えます。アイデア?

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}]

すべての辞書のすべてのキーからセットを作成し、次に、dictそれらが持っていない値で更新をループします。

を使用する代わりに、(3.xでは組み込みの2.x)とを使用することもitertools.chain.from_iterable()できますが、これは読みにくいと思います。reduce(or_, [dict.keys() for dict in dicts])functools.reduce()reduce()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 に答える