Python 如何最好地合并多个字典中的值?

Python 如何最好地合并多个字典中的值?,python,dictionary,merge,concatenation,Python,Dictionary,Merge,Concatenation,我创建了一个函数,它接受字典的多个参数,并返回一个连接字典。我在网上研究了一段时间关于合并词典的问题,并测试了一些有趣的词典。它们都导致更新(或覆盖)值 我的用例是传入字典,其中每个键都有一个值,并且需要一个具有相同或不同键的字典,以及每个键的值列表。这就是我对所谓词典“串联”的定义 以下是两个非常基本的词典: a = {1: 'a', 2: 'b', 3: 'c'} b = {1: 'd', 2: 'e', 3: 'f'} import collections def merge_dict

我创建了一个函数,它接受字典的多个参数,并返回一个连接字典。我在网上研究了一段时间关于合并词典的问题,并测试了一些有趣的词典。它们都导致更新(或覆盖)值

我的用例是传入字典,其中每个键都有一个值,并且需要一个具有相同或不同键的字典,以及每个键的值列表。这就是我对所谓词典“串联”的定义

以下是两个非常基本的词典:

a = {1: 'a', 2: 'b', 3: 'c'}
b = {1: 'd', 2: 'e', 3: 'f'}
import collections

def merge_dicts(*args):
    rtn = collections.defaultdict(list)
    for input_dict in args:
        for key, value in input_dict.items():
            rtn[key].append(value)
    return rtn
以下是函数:

def merge_dict(*args:dict):

    result = {}

    for arg in args:

        if not isinstance(arg, dict):
            return {}

        result_keys = result.keys()
        for key, value in arg.items():
            if key not in result_keys:
                result[key] = [value]
            else:
                result[key].append(value)

    return result
输出为:

print(merge_dict(a, b))
{1: ['a', 'd'], 2: ['b', 'e'], 3: ['c', 'f']}
print(merge_dict(a, b, c, d))
{1: ['a', 'd'], 2: ['b', 'e'], 3: ['c', 'f'], 4: ['g', 'j'], 5: ['h', 'k'], 6: ['i', 'l']}
我也可以对元组、数组、Numpy数组等执行相同的操作。请注意,此函数非常简单,除了作为
dict
实例之外,它不会进一步清理输入或验证数据结构

但是,我想知道是否有一种更有效的或“蟒蛇式”的方法来做到这一点。请随时添加您的输入

考虑添加这些具有不同键的词典:

c = {4: 'g', 5: 'h', 6: 'i'}
d = {4: 'j', 5: 'k', 6: 'l'}
输出为:

print(merge_dict(a, b))
{1: ['a', 'd'], 2: ['b', 'e'], 3: ['c', 'f']}
print(merge_dict(a, b, c, d))
{1: ['a', 'd'], 2: ['b', 'e'], 3: ['c', 'f'], 4: ['g', 'j'], 5: ['h', 'k'], 6: ['i', 'l']}
我将很快研究嵌套数据结构

因为你的回答,我做了以下几点:

import collections

def merge_dicts_1(*args):
    rtn = collections.defaultdict(list)
    for input_dict in args:
        for key, value in input_dict.items():
            rtn[key].append(value)
    return rtn

def merge_dicts_2(*args):
    rtn = {}
    for input_dict in args:
        for key, value in input_dict.items():
            rtn.setdefault(key, []).append(value)
    return rtn

if __name__ == "__main__":
    a = {1: 'a', 2: 'b', 3: 'c'}
    b = {1: 'd', 2: 'e', 3: 'f'}
    c = {4: 'g', 5: 'h', 6: 'i'}
    d = {4: 'j', 5: 'k', 6: 'l'}
    e = merge_dicts_1(a, b, c, d)
    f = merge_dicts_2(a, b, c, d)
    print(e)
    print(f)
    print(e == f)
这将打印以下内容:

defaultdict(<class 'list'>, {1: ['a', 'd'], 2: ['b', 'e'], 3: ['c', 'f'], 4: ['g', 'j'], 5: ['h', 'k'], 6: ['i', 'l']})
{1: ['a', 'd'], 2: ['b', 'e'], 3: ['c', 'f'], 4: ['g', 'j'], 5: ['h', 'k'], 6: ['i', 'l']}
True
defaultdict(,{1:['a',d',2:['b',e',3:['c',f',4:['g',j',5:['h',k',6:['i',l']})
{1:['a',d',2:['b',e',3:['c',f',4:['g',j',5:['h',k',6:['i',l']}
真的

谢谢大家!

像这样的怎么样

from functools import reduce

def _merge_two_dicts(combined, dictionary):
    for key, value in dictionary.items():
        combined.setdefault(key, []).append(value)
    return combined

def merge_dicts(*dicts):
    return reduce(_merge_two_dicts, dicts, {})


if __name__ == '__main__':
    a = {1: 'a', 2: 'b', 3: 'c'}
    b = {1: 'd', 2: 'e', 3: 'f', 4: 'g'}
    c = {1: 'h', 3: 'i', 5: 'j'}

    combined = merge_dicts(a, b, c)
    print(combined)    
输出:

{1:['a','d','h',2:['b','e',3:['c','f','i',4:['g',5:['j']}

类似的内容适用于任何数量的输入词典:

a = {1: 'a', 2: 'b', 3: 'c'}
b = {1: 'd', 2: 'e', 3: 'f'}
import collections

def merge_dicts(*args):
    rtn = collections.defaultdict(list)
    for input_dict in args:
        for key, value in input_dict.items():
            rtn[key].append(value)
    return rtn
诀窍是使用该结构在不存在新条目时自动生成新条目。在这种情况下,访问尚未存在的密钥会将其创建为空列表

注意,上面返回一个
defaultdict
对象。如果不希望这样做,可以将其转换回dict或使用此函数:

def merge_dicts(*args):
    rtn = {}
    for input_dict in args:
        for key, value in input_dict.items():
            rtn.setdefault(key, []).append(value)
    return rtn

对于只存在于一个dict中的键,应该怎么办?如果一个值是嵌套的dict怎么办?@Mr.Llama这些都是好问题。我可以让函数查找它,但这不是我的用例。它可以迭代键并递归检查其类型,但这不是函数的最初目的。@Mr.Llama I更新了问题,以包括添加不同键的字典的用例。函数按照我的预期处理了它。不是我所要求的,但仍然很好。我想知道更多关于
merge_dict({'a':1},{'b':2})应该返回什么的问题。应该是
{'a':[1],'b':[2]}
还是
{'a':1,'b':2}
?尝试使用
defaultdict(list)
谢谢您的回答。要使用它,我需要编写一个包装器函数,它接受多个参数并传递
args[0]
args[1]
,然后传递结果字典和
args[2]
,依此类推,以
合并两个dicts
。您将如何编写此代码来处理
*args
?Debug255:我(更新的)答案中的代码如何?如果它解决了你的问题,请考虑接受我的答案。请看,我接受了另一个答案,因为它解决了问题,我继续前进。我对你的答案投了赞成票。这两种行动都是回答问题时唯一可以做的两件积极的事情。我认为你的更新答案很聪明,使用reduce。所以,我将在周一测试它。谢谢。太好了,当我把我的4本字典交给它并打印字典时,它产生了
defaultdict(,{1:['a',d',2:['b',e',3:['c',f',4:['g',j',5:['h',k',6:['i',l'])