我想将两个词典融入一个新的词典。

x = {'a': 1, 'b': 2}
y = {'b': 3, 'c': 4}
z = merge(x, y)

>>> z
{'a': 1, 'b': 3, 'c': 4}

每当两个字典中都有一个关键 k 时,只应保留 y(k) 的值。


当前回答

我将所提出的与 perfplot 比较,并发现

x | y   # Python 3.9+

是最快的解决方案,与旧的好解决方案

{**x, **y}

temp = x.copy()
temp.update(y)

此分類上一篇


重复字符的代码:

from collections import ChainMap
from itertools import chain
import perfplot


def setup(n):
    x = dict(zip(range(n), range(n)))
    y = dict(zip(range(n, 2 * n), range(n, 2 * n)))
    return x, y


def copy_update(x, y):
    temp = x.copy()
    temp.update(y)
    return temp


def add_items(x, y):
    return dict(list(x.items()) + list(y.items()))


def curly_star(x, y):
    return {**x, **y}


def chain_map(x, y):
    return dict(ChainMap({}, y, x))


def itertools_chain(x, y):
    return dict(chain(x.items(), y.items()))


def python39_concat(x, y):
    return x | y


b = perfplot.bench(
    setup=setup,
    kernels=[
        copy_update,
        add_items,
        curly_star,
        chain_map,
        itertools_chain,
        python39_concat,
    ],
    labels=[
        "copy_update",
        "dict(list(x.items()) + list(y.items()))",
        "{**x, **y}",
        "chain_map",
        "itertools.chain",
        "x | y",
    ],
    n_range=[2 ** k for k in range(18)],
    xlabel="len(x), len(y)",
    equality_check=None,
)
b.save("out.png")
b.show()

其他回答

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z = dict(x.items() + y.items())
print z

对于两个字典中的关键物品(“b”),您可以通过将最后一个放在输出中来控制哪个。

另一个,更细致的选择:

z = dict(x, **y)

注意:这已成为一个受欢迎的答案,但重要的是要指出的是,如果 y 有任何不紧密的密钥,事实上,这完全是CPython实施细节的滥用,并且它不在Python 3或PyPy,IronPython,或Jython工作。

在您的情况下,您可以:

z = dict(list(x.items()) + list(y.items()))

因此,如您所需,将最终定位定位为z,并使关键b的值由第二(y)定位的值正确上调:

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = dict(list(x.items()) + list(y.items()))
>>> z
{'a': 1, 'c': 11, 'b': 10}

如果您使用 Python 2, 您甚至可以删除列表() 通话。

>>> z = dict(x.items() + y.items())
>>> z
{'a': 1, 'c': 11, 'b': 10}

如果您使用 Python 版本 3.9.0a4 或更高版本,则可以直接使用:

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z = x | y
print(z)
{'a': 1, 'c': 11, 'b': 10}

z = MergeDict(x, y)

当使用这个新对象时,它将像合并词典一样行事,但它将有持续的创作时间和持续的记忆脚印,同时让原始词典无触摸。

当然,如果你使用结果很多,那么你会在某个时候达到创建一个真正的合并词典会是最快的解决方案的界限。

a = { 'x': 3, 'y': 4 }
b = MergeDict(a)  # we merge just one dict
b['x'] = 5
print b  # will print {'x': 5, 'y': 4}
print a  # will print {'y': 4, 'x': 3}

class MergeDict(object):
  def __init__(self, *originals):
    self.originals = ({},) + originals[::-1]  # reversed

  def __getitem__(self, key):
    for original in self.originals:
      try:
        return original[key]
      except KeyError:
        pass
    raise KeyError(key)

  def __setitem__(self, key, value):
    self.originals[0][key] = value

  def __iter__(self):
    return iter(self.keys())

  def __repr__(self):
    return '%s(%s)' % (
      self.__class__.__name__,
      ', '.join(repr(original)
          for original in reversed(self.originals)))

  def __str__(self):
    return '{%s}' % ', '.join(
        '%r: %r' % i for i in self.iteritems())

  def iteritems(self):
    found = set()
    for original in self.originals:
      for k, v in original.iteritems():
        if k not in found:
          yield k, v
          found.add(k)

  def items(self):
    return list(self.iteritems())

  def keys(self):
    return list(k for k, _ in self.iteritems())

  def values(self):
    return list(v for _, v in self.iteritems())

如果你不想转动X,

x.update(y) or x

(x.update(y), x)[-1]

如果你还没有X在变量,你可以使用Lambda做一个地方,而不使用任务声明,这意味着使用Lambda作为一个Let表达,这是一个常见的技术在功能语言,但可能是无神论的。

(lambda x: x.update(y) or x)({'a': 1, 'b': 2})

(x := {'a': 1, 'b': 2}).update(y) or x

(lambda x={'a': 1, 'b': 2}: x.update(y) or x)()

如果你想要一个副本,PEP 584 风格 x <unk> y 是最 Pythonic 的 3.9+. 如果你需要支持更古老的版本,PEP 448 风格 {**x, **y} 是最容易的 3.5+. 但如果它不在你的(甚至更古老的) Python 版本,让表达模式也在这里工作。

(lambda z=x.copy(): z.update(y) or z)()

(当然,这可能相当于(z := x.copy())。更新(y)或z,但如果您的Python版本足够新,那么PEP 448风格将可用。