【问题标题】:How best to merge the values from multiple dictionaries?如何最好地合并来自多个字典的值?
【发布时间】:2019-04-06 04:33:24
【问题描述】:

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

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

这里有两个非常基本的字典:

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

函数如下:

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

我可以对元组、数组、Numpy 数组等做同样的事情。请注意,这个函数非常简单,除了作为 dict 实例之外,它不会清理输入或验证数据结构。

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

考虑使用不同的键添加这些字典:

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

输出是:

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

谢谢!

【问题讨论】:

  • 只存在于一个字典中的键应该怎么办?如果一个值是一个嵌套的 dict 会发生什么?
  • @Mr.Llama 这些都是好问题。我可以让函数查找它,但这不是我的用例。它可以遍历键并递归检查其类型,但这不是该函数的最初目的。
  • @Mr.Llama 我更新了问题以包括添加不同键的字典的用例。该函数按我的预期处理它。
  • 不是我问的那样,但还是不错的。我想知道更多 merge_dict({'a': 1}, {'b': 2}) 应该返回什么。应该是{'a': [1], 'b': [2]} 还是{'a': 1, 'b': 2}
  • 尝试使用defaultdict(list)

标签: python dictionary merge concatenation


【解决方案1】:

这样的方法适用于任意数量的输入字典:

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 结构在新条目不存在时自动创建它们。在这种情况下,访问一个尚不存在的键会将其创建为一个空列表。

请注意,上面返回一个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

【讨论】:

  • 太棒了,当我将我的 4 个字典传递给它并打印字典时,这导致了 defaultdict(&lt;class 'list'&gt;, {1: ['a', 'd'], 2: ['b', 'e'], 3: ['c', 'f'], 4: ['g', 'j'], 5: ['h', 'k'], 6: ['i', 'l']})
【解决方案2】:

这样的事情怎么样?

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

【讨论】:

  • 感谢您的回答。要使用它,我需要编写一个包装函数,它接受多个参数并传递args[0]args[1],然后是生成的字典和args[2],以此类推到merge_two_dicts。你会如何写这个来处理*args
  • Debug255:我的(更新的)答案中的代码呢?如果它解决了您的问题,请考虑接受我的回答。请看What should I do when someone answers my question?
  • 我接受了另一个答案,因为它解决了这个问题,我继续前进。我确实投票赞成你的答案。这两个动作是唯一与答案有关的两件积极的事情。我认为您使用reduce的更新答案很聪明。所以,我会在星期一测试它。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-10
  • 1970-01-01
  • 1970-01-01
  • 2011-07-11
  • 1970-01-01
  • 1970-01-01
  • 2017-07-14
相关资源
最近更新 更多