【问题标题】:How to concatenate two dictionaries to create a new one? [duplicate]如何连接两个字典以在 Python 中创建一个新字典? [复制]
【发布时间】:2010-12-19 09:20:20
【问题描述】:

假设我有三个 dicts

d1={1:2,3:4}
d2={5:6,7:9}
d3={10:8,13:22}

如何创建一个结合这三个字典的新d4?即:

d4={1:2,3:4,5:6,7:9,10:8,13:22}

【问题讨论】:

  • d4 = {**d1, **d2, **d3} --> {1: 2, 3: 4, 5: 6, 7: 9, 10: 8, 13: 22 }

标签: python dictionary concatenation


【解决方案1】:

这是一个单行(imports 不算数:),可以很容易地推广到连接 N 个字典:

Python 3

from itertools import chain
dict(chain.from_iterable(d.items() for d in (d1, d2, d3)))

和:

from itertools import chain
def dict_union(*args):
    return dict(chain.from_iterable(d.items() for d in args))

Python 2.6 和 2.7

from itertools import chain
dict(chain.from_iterable(d.iteritems() for d in (d1, d2, d3))

输出:

>>> from itertools import chain
>>> d1={1:2,3:4}
>>> d2={5:6,7:9}
>>> d3={10:8,13:22}
>>> dict(chain.from_iterable(d.iteritems() for d in (d1, d2, d3)))
{1: 2, 3: 4, 5: 6, 7: 9, 10: 8, 13: 22}

泛化为连接 N 个字典:

from itertools import chain
def dict_union(*args):
    return dict(chain.from_iterable(d.iteritems() for d in args))

我知道我参加这个聚会有点晚了,但我希望这对某人有所帮助。

【讨论】:

  • imports 计数。但是这里的解决方案还是很有趣的
  • 对于 python 3.6,它应该是 d.items() 而不是 d.iteritems()。感谢您的贡献!
  • 只是完美主义者的一个细节,Python3的第一个版本缺少右括号。
  • @sandroscodeller 谢谢!固定。
  • 我不明白为什么 Python 没有为这种常用的字典连接实现“+”运算符。
【解决方案2】:
  1. 最慢且在 Python3 中不起作用:连接 items 并在结果列表中调用 dict

    $ python -mtimeit -s'd1={1:2,3:4}; d2={5:6,7:9}; d3={10:8,13:22}' \
    'd4 = dict(d1.items() + d2.items() + d3.items())'
    
    100000 loops, best of 3: 4.93 usec per loop
    
  2. 最快:充分利用dict 构造函数,然后是update

    $ python -mtimeit -s'd1={1:2,3:4}; d2={5:6,7:9}; d3={10:8,13:22}' \
    'd4 = dict(d1, **d2); d4.update(d3)'
    
    1000000 loops, best of 3: 1.88 usec per loop
    
  3. 中级:update 循环调用最初为空的字典:

    $ python -mtimeit -s'd1={1:2,3:4}; d2={5:6,7:9}; d3={10:8,13:22}' \
    'd4 = {}' 'for d in (d1, d2, d3): d4.update(d)'
    
    100000 loops, best of 3: 2.67 usec per loop
    
  4. 或者,等效地,一个 copy-ctor 和两个更新:

    $ python -mtimeit -s'd1={1:2,3:4}; d2={5:6,7:9}; d3={10:8,13:22}' \
    'd4 = dict(d1)' 'for d in (d2, d3): d4.update(d)'
    
    100000 loops, best of 3: 2.65 usec per loop
    

我推荐方法(2),我特别建议避免(1)(这也为连接的项目临时数据结构列表占用了 O(N) 额外的辅助内存)。

【讨论】:

  • 我不明白为什么d4 = dict(d1, **dict(d2, **d3)) 没有比#2 快,但事实并非如此。
  • 以上 1 最好是处理小型字典,因为我认为它更清晰。
  • 除非已知所有键都是字符串,否则选项 2 是对 Python 2 实现细节的滥用(事实上,在 C 中实现的一些内置函数绕过了对关键字参数的预期检查)。在 Python 3(和 PyPy)中,选项 2 将因非字符串键而失败。
  • 我要补充一点,d1.items() + d2.items() 在 Python 3 中不起作用。
  • 在 Python 3.5+ 中,可以使用 ** 表示法:d1={1:2,3:4}; d2={5:6,7:9}; d3={10:8,13:22}; d4 = {**d1, **d2, **d3},这对我来说比上面的 #3 或 #4 快了近 3 倍(每个循环 0.228 微秒与 0.661 或 0.595 微秒分别用于#3 或 4)。如上所述,#1 和 #2 不适用于 Python 3。
【解决方案3】:

使用 dict 构造函数

d1={1:2,3:4}
d2={5:6,7:9}
d3={10:8,13:22}

d4 = reduce(lambda x,y: dict(x, **y), (d1, d2, d3))

作为一个函数

from functools import partial
dict_merge = partial(reduce, lambda a,b: dict(a, **b))

使用dict.update() 方法可以消除创建中间字典的开销:

from functools import reduce
def update(d, other): d.update(other); return d
d4 = reduce(update, (d1, d2, d3), {})

【讨论】:

    【解决方案4】:

    您可以使用update() 方法来构建一个包含所有项目的新字典:

    dall = {}
    dall.update(d1)
    dall.update(d2)
    dall.update(d3)
    

    或者,在一个循环中:

    dall = {}
    for d in [d1, d2, d3]:
      dall.update(d)
    

    【讨论】:

    • 更新不构建新字典。它(如预期的那样)更新了原始版本。
    • @A.J.Rouvoet:在这种情况下,“原始字典”是dall 中的全新空字典。这个新字典会反复更新以包含所有元素。有意更改dall
    • 啊,我的评论纯粹是针对您第一句话的措辞方式。它暗示了一些并非如此的事情。虽然我承认投反对票可能有点苛刻。
    • 逻辑上使用更新我们可以通过更新其他字典来创建新字典,如果我们不需要以前的字典,我们可以在 for 循环中使用 del d1 删除它们。
    【解决方案5】:
    d4 = dict(d1.items() + d2.items() + d3.items())
    

    或者(据说更快):

    d4 = dict(d1)
    d4.update(d2)
    d4.update(d3)
    

    这两个答案来自的上一个 SO 问题是 here

    【讨论】:

    • 可以用d4 = copy(d1)代替d4 = dict(d1)
    • @ds:这似乎行不通。也许你的意思是from copy import copy; d4 = copy(d1) 或者d4 = d1.copy()
    • 第一个版本不适用于 Python3。
    • 也许d4 = d1.copy()
    • 它在 Python 3 中确实有效,但您必须将 dict_items 对象转换为真正的 list 对象。这是 Python 3 将次要性能优化优先于简单性和易用性的另一种情况。
    猜你喜欢
    • 1970-01-01
    • 2019-09-17
    • 1970-01-01
    • 1970-01-01
    • 2012-01-15
    • 1970-01-01
    • 1970-01-01
    • 2013-02-17
    • 1970-01-01
    相关资源
    最近更新 更多