比较字典时,更新而不是覆盖值

4

我不需要这样的内容:

如何在单个表达式中合并两个字典?

一种更新Python字典而不覆盖子字典的通用方法

Python:通过更新而不覆盖值来合并字典

我需要这样的内容:

输入:

d1 = {'a': 'a', 'b': 'b'}
d2 = {'b': 'c', 'c': 'd'}

输出:

new_dict = {'a': ['a'], 'b': ['b', 'c'], 'c': ['d']}

我有以下代码可以运行,但我想知道是否存在更有效的方法:
首先,我创建了一个名为“unique_vals”的列表,其中存储了两个字典中都存在的所有值。 接下来,创建了一个新字典,其中存储了两个字典中都存在的所有值。
unique_vals = []
new_dict = {}
for key in list(d1.keys())+list(d2.keys()) :
    unique_vals = []
    try:
        for val in d1[key]:
            try:
                for val1 in d2[key]:
                    if(val1 == val) and (val1 not in unique_vals):
                        unique_vals.append(val)
            except:
                continue
    except:        
        new_dict[key] = unique_vals
    new_dict[key] = unique_vals

然后,对于两个字典中未列在这个新字典中的每个值,这些值都会被添加到新字典中。
for key in d1.keys():
      for val in d1[key]:
          if val not in new_dict[key]:
              new_dict[key].append(val)
for key in d2.keys():
    for val in d2[key]:
        if val not in new_dict[key]:
            new_dict[key].append(val)
3个回答

3
也许可以使用一个 defaultdict
>>> d1 = {'a': 'a', 'b': 'b'} 
>>> d2 = {'b': 'c', 'c': 'd'}
>>> from collections import defaultdict                                         
>>>                                                                             
>>> merged = defaultdict(list)                                                  
>>> dicts = [d1, d2]                                                            
>>> for d in dicts: 
...:     for key, value in d.items(): 
...:         merged[key].append(value) 
...:                                                                            
>>> merged                                                                      
defaultdict(list, {'a': ['a'], 'b': ['b', 'c'], 'c': ['d']})

这适用于 dicts 列表中的任意数量的字典。

作为一个函数:

def merge_dicts(dicts):
    merged = defaultdict(list)

    for d in dicts:
        for key, value in d.items():
            merged[key].append(value)

    return merged

3
这里有一个简化版:
d1 = {'a': 'a', 'b': 'b'}
d2 = {'b': 'c', 'c': 'd'}

new_dict = {key: [value] for key, value in d1.items()}
for key, value in d2.items():
    try:
        new_dict[key].append(value)
    except:
        new_dict[key] = [value]

输出:

{'a': ['a'], 'b': ['b', 'c'], 'c': ['d']}

这与@actual_panda的方法相同,不同之处在于我没有在字典上创建循环,而是简单地编写了2个for循环,因为您只有2个输入字典;并且我考虑到了一个键可能存在于第二个字典中而不在第一个字典中的情况,并使用try/except处理了它。 - Mathieu
谢谢!我刚刚意识到我还有另一个输入。实际上,我的输入如下: d1 = {'a': ['a'], 'b': ['b', 'c']} d2 = {'b': ['d'], 'c': ['e','f']} - aze45sq6d
@aze45sq6d 然后将 append 替换为 extend,并从 value 中删除括号,因为您的值已经是列表;这样就可以工作了。 - Mathieu

2

编辑:下面的解决方案适用于原始问题,有关更新后的问题,请查看其他答案或重复内容。

一行解决方案:

def merge_dicts(*dcts):
    return {k: [d[k] for d in dcts if k in d] for k in {k for d in dcts for k in d.keys()}}

d1 = {'a': 'a', 'b': 'b'}
d2 = {'b': 'c', 'c': 'd'}
print(merge_dicts(d1, d2))
# {'c': ['d'], 'a': ['a'], 'b': ['b', 'c']}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接