在 Python 的字典中添加缺失的键

Adding missing keys in dictionary in Python

我有一个词典列表:

L = [{0:1,1:7,2:3,4:8},{0:3,2:6},{1:2,4:6}....{0:2,3:2}]. 

如您所见,字典的长度不同。我需要的是将缺失的 keys:values 添加到每个字典中,使它们具有相同的长度:

L1 = [{0:1,1:7,2:3,4:8},{0:3,1:0,2:6,3:0,4:0},{0:0, 1:2,3:0,4:6}....{0:2,1:0,2:0,3:2,4:0}], 

表示为缺失值补零。最大长度没有预先给出,所以可能只能通过列表迭代才能得到它。

我尝试用 defaultdicts 做一些东西,比如 L1 = defaultdict(L) 但我似乎不太理解它是如何工作的。

您必须进行两次传递:一次获得所有键的并集,另一次添加缺失的键:

max_key = max(max(d) for d in L)
empty = dict.fromkeys(range(max_key + 1), 0)
L1 = [dict(empty, **d) for d in L]

这使用 'empty' 字典作为基础来快速生成 all 键;该词典的新副本加上原始词典会产生您想要的输出。

请注意,这假设您的密钥始终是连续的。如果不是,您可以生成所有现有键的并集:

empty = dict.fromkeys(set().union(*L), 0)
L1 = [dict(empty, **d) for d in L]

演示:

>>> L = [{0: 1, 1: 7, 2: 3, 4: 8}, {0: 3, 2: 6}, {1: 2, 4: 6}, {0: 2, 3: 2}]
>>> max_key = max(max(d) for d in L)
>>> empty = dict.fromkeys(range(max_key + 1), 0)
>>> [dict(empty, **d) for d in L]
[{0: 1, 1: 7, 2: 3, 3: 0, 4: 8}, {0: 3, 1: 0, 2: 6, 3: 0, 4: 0}, {0: 0, 1: 2, 2: 0, 3: 0, 4: 6}, {0: 2, 1: 0, 2: 0, 3: 2, 4: 0}]

或设置方法:

>>> empty = dict.fromkeys(set().union(*L), 0)
>>> [dict(empty, **d) for d in L]
[{0: 1, 1: 7, 2: 3, 3: 0, 4: 8}, {0: 3, 1: 0, 2: 6, 3: 0, 4: 0}, {0: 0, 1: 2, 2: 0, 3: 0, 4: 6}, {0: 2, 1: 0, 2: 0, 3: 2, 4: 0}]

上述使用 dict(d1, **d2) 将两个词典合并成一个新词典的方法在 Python 2 中始终有效。在 Python 3 中,已对您使用哪种键设置了额外的限制可以使用这个技巧;第二个字典只允许 字符串键 。对于此示例,您有 numeric 键,但您可以改用字典解包:

{**empty, **d}  # Python 3 dictionary unpacking

这将适用于 Python 3.5 和更新版本。

这只是一个解决方案,但我认为它简单明了。请注意,它会 就地 修改词典,因此如果您希望它们被 复制 ,请告诉我,我会相应地进行修改。

keys_seen = []
for D in L:  #loop through the list
    for key in D.keys():  #loop through each dictionary's keys
        if key not in keys_seen:  #if we haven't seen this key before, then...
            keys_seen.append(key)  #add it to the list of keys seen

for D1 in L:  #loop through the list again
    for key in keys_seen:  #loop through the list of keys that we've seen
        if key not in D1:  #if the dictionary is missing that key, then...
            D1[key] = 0  #add it and set it to 0

也许不是最优雅的解决方案,但应该可行:

L = [{0:1,1:7,2:3,4:8},{0:3,2:6},{1:2,4:6},{0:2,3:2}]

alldicts = {}
for d in L:
    alldicts.update(d)

allkeys = alldicts.keys()

for d in L:
    for key in allkeys:
        if key not in d:
            d[key] = 0

print(L)

注意一点:更改 L

>>> allkeys = frozenset().union(*L)
>>> for i in L:
...    for j in allkeys:
...        if j not in i:
...            i[j]=0

>>> L
[{0: 1, 1: 7, 2: 3, 3: 0, 4: 8}, {0: 3, 1: 0, 2: 6, 3: 0, 4: 0}, {0: 0, 1: 2, 2:
 0, 3: 0, 4: 6}, {0: 2, 1: 0, 2: 0, 3: 2, 4: 0}]

除非 None 是您所拥有的字典键的有效值,否则这里是一个很好的解决方案

L = [{0: 1, 1: 7, 2: 3, 4: 8}, {0: 3, 2: 6}, {1: 2, 4: 6}, {0: 2, 3: 2}]
for i0, d0 in enumerate(L[:-1]):
    for d1 in L[i0:]:
        _ = [d0.__setitem__(k,d1[k]) for k in d1 if d0.get(k,None) is None]
        _ = [d1.__setitem__(k,d0[k]) for k in d0 if d1.get(k,None) is None]

print(L)
>>> [{0: 1, 1: 7, 2: 3, 3: 2, 4: 8}, {0: 3, 1: 2, 2: 6, 3: 2, 4: 6}, {0: 2, 1: 2, 2: 3, 3: 2, 4: 6}, {0: 2, 1: 7, 2: 3, 3: 2, 4: 8}]

这又快又苗条:

missing_keys = set(dict1.keys()) - set(dict2.keys())
for k in missing_keys:
    dict1[k] = dict2[k]