合并字典,不覆盖先前的值,其中值为列表

4
我知道如何合并Python字典,包括:不覆盖值的合并字典多个Python字典的合并如何合并多个具有相同键的字典?以及如何在单个表达式中合并两个Python字典
然而,我的问题略有不同。假设我有这三个字典:
dict_a = {'a': [3.212], 'b': [0.0]}
dict_b = {'a': [923.22, 3.212], 'c': [123.32]}
dict_c = {'b': [0.0]}

合并后的结果应该是:
result_dict = {'a': [3.212, 3.212, 923.22], 'b': [0.0, 0.0], 'c': [123.32]}

这段代码可以正常运行,但会在列表中嵌套其他列表。
result_dict = {}
dicts = [dict_a, dict_b, dict_c]

for d in dicts:
    for k, v in d.iteritems():
        result_dict.setdefault(k, []).append(v)

使用extend而不是append可以防止嵌套列表,但如果键不存在,则无法工作。因此,基本上应该执行一个没有覆盖的update,如其他线程中所述。

抱歉,这是我方面的错误。昨天太晚了,我没有注意到抛出错误的行不是我想象的那一行,因此假设我的字典已经具有上述结构。mgilson实际上是正确的,假设它与TypeError有关。确切地说,是“不可迭代浮点数”。


2
你能解释一下为什么 extend 不起作用吗?setdefault(k, []) 不应该解决不存在的键问题吗? - DSM
1
为什么a的结果列表会以那个顺序结束?我本来期望是:[3.212,923.22,3.212] - mgilson
@mgilson 是的,抱歉。我已经在脑海中排序了。但应该按照你说的方式进行。 - cherrun
1个回答

4

我相信在这里使用.extend是可行的...

>>> dict_a = {'a': [3.212], 'b': [0.0]}
>>> dict_b = {'a': [923.22, 3.212], 'c': [123.32]}
>>> dict_c = {'b': [0.0]}
>>> result_dict = {}
>>> dicts = [dict_a, dict_b, dict_c]
>>> 
>>> for d in dicts:
...     for k, v in d.iteritems():
...         result_dict.setdefault(k, []).extend(v)
... 
>>> result_dict
{'a': [3.212, 923.22, 3.212], 'c': [123.32], 'b': [0.0, 0.0]}

魔法在于 `dict.setdefault` 方法。如果键不存在,`setdefault` 将使用您提供的默认值添加一个新键。然后返回该默认值,可以对其进行修改。
请注意,如果项目 `v` 不可迭代,则此解决方案将有问题。也许这就是您的意思?例如,如果 `dict_a = {'a': [3.212], 'b': 0.0}`。
在这种情况下,我认为您需要使用 `try-except` 子句捕获 `TypeError: type object is not iterable`。
for d in dicts:
    for k, v in d.iteritems():
        try:
            result_dict.setdefault(k, []).extend(v)
        except TypeError:
            result_dict[k].append(v)

我没有一直关注abc中的所有内容。有什么基本上是“标量”的东西吗?即“不可迭代,或者可迭代但是字符串”? - DSM
我只是想说,TypeError方法无法防止类似标量但可迭代的对象(例如字符串)进入.extend分支并将“Fred”转换为“F”,“r”,“e”,“d”。 - DSM
啊...你是在指出str没有.__iter__函数这个事实吗?幸运的是,Python3.x已经解决了这个问题...而且我认为字符串是唯一常被视为标量但也可迭代的对象... - mgilson
哎呀,我好像没有很好地解释清楚:^) 没有 Python 3 的连接,只是这段代码可以适用于标量数字值,但不能适用于标量字符串值,我想知道是否还有一些聪明的技巧,除了not isinstance(v, basestring),好像我又落后了。 - DSM
@mgilson 好的假设。我编辑了我的第一篇帖子。确实是 TypeError。你的解决方案很好,但我不明白的是,如果我在解释器中尝试这样做,当我尝试执行 result_dict['foo'].append(3.14) 时,它会给我一个 KeyError。你能解释一下为什么吗?在我的 Python 脚本中似乎可以工作。 - cherrun
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接