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

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

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

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


当前回答

2 词典

def union2(dict1, dict2):
    return dict(list(dict1.items()) + list(dict2.items()))

n 字典

def union(*dicts):
    return dict(itertools.chain.from_iterable(dct.items() for dct in dicts))

查看 https://mathieularose.com/how-not-to-flatten-a-list-of-lists-in-python/

其他回答

我认为我的丑陋的单线只需要在这里。

z = next(z.update(y) or z for z in [x.copy()])
# or
z = (lambda z: z.update(y) or z)(x.copy())

单一表达,永远不要敢用它。

我知道Python 3有这个 {**x, **y} 事物,它是正确的事情使用(以及转到Python 3 如果你仍然有Python 2是正确的事情)。

一个联合的OP的两个词典会是这样的东西:

{'a': 1, 'b': 2, 10, 'c': 11}

具体而言,两个实体(x 和 y)的联盟包含所有 x 和/或 y 的元素,不幸的是,OP 所要求的不是联盟,尽管职位的标题。

我的下面的代码既不优雅,也不是单线,但我认为它与联盟的意义一致。

从OP的例子:

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}

z = {}
for k, v in x.items():
    if not k in z:
        z[k] = [(v)]
    else:
        z[k].append((v))
for k, v in y.items():
    if not k in z:
        z[k] = [(v)]
    else:
        z[k].append((v))

{'a': [1], 'b': [2, 10], 'c': [11]}

无论你想要的列表都可以改变,但上述将工作,如果一个词典包含列表(和列表)作为每个词典中的值。

(仅适用于 Python 2.7*;有更简单的解决方案适用于 Python 3*。

如果您不拒绝进口标准图书馆模块,您可以

from functools import reduce

def merge_dicts(*dicts):
    return reduce(lambda a, d: a.update(d) or a, dicts, {})

(Lambda中的一个或一点是必要的,因为 dict.update 总是返回 没有成功。

深深的定律:

from typing import List, Dict
from copy import deepcopy

def merge_dicts(*from_dicts: List[Dict], no_copy: bool=False) -> Dict :
    """ no recursion deep merge of two dicts

    By default creates fresh Dict and merges all to it.

    no_copy = True, will merge all dicts to a fist one in a list without copy.
    Why? Sometime I need to combine one dictionary from "layers".
    The "layers" are not in use and dropped immediately after merging.
    """

    if no_copy:
        xerox = lambda x:x
    else:
        xerox = deepcopy

    result = xerox(from_dicts[0])

    for _from in from_dicts[1:]:
        merge_queue = [(result, _from)]
        for _to, _from in merge_queue:
            for k, v in _from.items():
                if k in _to and isinstance(_to[k], dict) and isinstance(v, dict):
                    # key collision add both are dicts.
                    # add to merging queue
                    merge_queue.append((_to[k], v))
                    continue
                _to[k] = xerox(v)

    return result

使用:

print("=============================")
print("merge all dicts to first one without copy.")
a0 = {"a":{"b":1}}
a1 = {"a":{"c":{"d":4}}}
a2 = {"a":{"c":{"f":5}, "d": 6}}
print(f"a0 id[{id(a0)}] value:{a0}")
print(f"a1 id[{id(a1)}] value:{a1}")
print(f"a2 id[{id(a2)}] value:{a2}")
r = merge_dicts(a0, a1, a2, no_copy=True)
print(f"r  id[{id(r)}] value:{r}")

print("=============================")
print("create fresh copy of all")
a0 = {"a":{"b":1}}
a1 = {"a":{"c":{"d":4}}}
a2 = {"a":{"c":{"f":5}, "d": 6}}
print(f"a0 id[{id(a0)}] value:{a0}")
print(f"a1 id[{id(a1)}] value:{a1}")
print(f"a2 id[{id(a2)}] value:{a2}")
r = merge_dicts(a0, a1, a2)
print(f"r  id[{id(r)}] value:{r}")

在您的情况下,您可以:

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}