Dict合并在词典理解中

时间:2016-06-02 06:45:20

标签: python dictionary syntax-error python-3.5 dict-comprehension

在python 3.5中,我们可以通过使用双splat解包来合并dicts

>>> d1 = {1: 'one', 2: 'two'}
>>> d2 = {3: 'three'}
>>> {**d1, **d2}
{1: 'one', 2: 'two', 3: 'three'}

冷却。但它似乎并未概括为动态用例:

>>> ds = [d1, d2]
>>> {**d for d in ds}
SyntaxError: dict unpacking cannot be used in dict comprehension

相反,我们必须做reduce(lambda x,y: {**x, **y}, ds, {}),这似乎更加丑陋。为什么解析器不允许“一种明显的方法”,当表达式中似乎没有任何歧义时?

5 个答案:

答案 0 :(得分:11)

这不完全是你问题的答案,但我考虑使用ChainMap作为一种惯用而优雅的方式来做你的建议(合并字典在线):

>>> d1 = {1: 'one', 2: 'two'}
>>> d2 = {3: 'three'}
>>> ds = [d1, d2]
>>> dict(ChainMap(*ds))
{1: 'one', 2: 'two', 3: 'three'}

虽然它不是一个特别透明的解决方案,但由于许多程序员可能不确切知道ChainMap的工作原理。请注意(正如@AnttiHaapala指出的那样)"首先使用"因此,根据您的意图,您可能需要先致电reversed,然后再将dict传递给ChainMap

>>> d2 = {3: 'three', 2:'LOL'}
>>> dict(ChainMap(*ds))
{1: 'one', 2: 'two', 3: 'three'}

>>> dict(ChainMap(*reversed(ds)))
{1: 'one', 2: 'LOL', 3: 'three'}

答案 1 :(得分:6)

对我来说,显而易见的方法是:

-Wconversion

这很快,可能非常有效。我不知道我可以代表python开发人员,但我不知道你期望的版本更容易阅读。例如,由于缺少d_out = {} for d in ds: d_out.update(d) ,你的理解看起来更像是对我的理解。 FWIW,我认为没有任何技术原因(例如解析器含糊不清),他们无法添加这种形式的理解解包。

显然,these forms were proposed,但没有足够普遍的支持来保证实施它们(还有)。

答案 2 :(得分:0)

final = {}
for data in [d1, d2]:
    final = {**final,**data}

答案 3 :(得分:0)

您可以定义此功能:

from collections import ChainMap
def mergeDicts(l):
    return dict(ChainMap(*reversed(list(l))))

然后您可以像这样使用它:

>>> d1 = {1: 'one', 2: 'two'}
>>> d2 = {3: 'three'}
>>> ds = [d1, d2]
>>> mergeDicts(ds)
{1: 'one', 2: 'two', 3: 'three'}

答案 4 :(得分:0)

您可以使用itertools.chainitertools.chain.from_iterable

import itertools

ds = [{'a': 1, 'b': 2}, {'c': 30, 'b': 40}]

merged_d = dict(itertools.chain(*(d.items() for d in ds)))
print(merged_d)  # {'a': 1, 'b': 40, 'c': 30}