如何在Python中合并列表中的嵌套字典?
比如说,如果我得到了这样的结果:
[{'Germany': {"Luge - Men's Singles": 'Gold'}},
{'Germany': {"Luge - Men's Singles": 'Silver'}},
{'Italy': {"Luge - Men's Singles": 'Bronze'}}]
[{'Germany': {"Luge - Women's Singles": 'Gold'}},
{'Austria': {"Luge - Women's Singles": 'Silver'}},
{'Germany': {"Luge - Women's Singles": 'Bronze'}}]
[{'Austria': {'Luge - Doubles': 'Gold'}},
{'Latvia': {'Luge - Doubles': 'Silver'}},
{'Germany': {'Luge - Doubles': 'Bronze'}}]
我想把这些结果整理一下,让所有关于德国的比赛都放在一个标题下。比如说,德国的结果应该是:德国:单人雪橇 - 男子:金牌、银牌,单人雪橇 - 女子:金牌、铜牌,双人雪橇:铜牌。
谢谢大家的帮助。
补充说明:这是我直接从Python的命令行复制过来的,希望能减少混淆:
[{'Germany': {"Luge - Men's Singles": 'Gold'}}, {'Germany': {"Luge - Men's Singles": 'Silver'}}, {'Italy': {"Luge - Men's Singles": 'Bronze'}}] [{'Germany': {"Luge - Women's Singles": 'Gold'}}, {'Austria': {"Luge - Women's Singles": 'Silver'}}, {'Germany': {"Luge - Women's Singles": 'Bronze'}}] [{'Austria': {'Luge - Doubles': 'Gold'}}, {'Latvia': {'Luge - Doubles': 'Silver'}}, {'Germany': {'Luge - Doubles': 'Bronze'}}]
抱歉,我还是新手。这个结果循环了三次,每次对应不同的比赛。我在想,能不能在最后一次循环后把这些结果合并成我想要的格式呢?
2 个回答
import collections
merged_result = collections.defaultdict(list)
for L in listoflistsofdicts:
for d in L:
for k in d:
merged_result[k].append(d[k])
或者如果你只有一个字典的列表,而不是字典的列表的列表(从你的问题来看很难判断!),那么只需要循环的
for d in listofdicts:
for k in d:
merged_result[k].append(d[k])
部分。
如果你想要的是字符串而不是列表作为merged_result
的值,那么在上面的代码后面加上
for k in merged_result:
merged_result[k] = ', '.join(merged_result[k])
或者,等效的(但是构建一个新的普通字典,而不是使用defaultdict):
merged_result = dict((k, ', '.join(v)) for k, v in merged_result.iteritems())
(这假设你在使用Python 2.* -- 在Python 3中,使用.items
代替.iteritems
)。
编辑:看了下示例代码,发现对于字典的列表的列表来说,语法是无效的(缺少逗号),所以我也展示了如何处理这个问题。
(抱歉,我其实是想在Alex Martelli的回答下评论,因为我的回答是基于他的;但我最开始发帖时没有足够的声望来评论)
Alex的回答实际上没有产生预期的结果。我不是说列表、字典的细节问题,或者列表之间缺少逗号(稍后会详细说)。但原问题想要的结果是按国家和比赛来汇总所有的奖牌。Alex的解决方案会给出:
> 'Germany': [{"Luge - Men's Singles": 'Gold'},
{"Luge - Men's Singles": 'Silver'},
{"Luge - Women's Singles": 'Gold'},
{"Luge - Women's Singles": 'Bronze'},
{'Luge - Doubles': 'Bronze'}]
但我认为原问题实际上是想要:
> 'Germany': [{"Luge - Men's Singles": ['Gold', 'Silver']},
{"Luge - Women's Singles": ['Gold', 'Bronze'},
{'Luge - Doubles': 'Bronze'}]
问题中的数据有点混乱,我看到两种可能性:
1) 显示的数据实际上是三个不同的例子,任务是分别合并每个列表中的字典条目。也就是说,给定
[{'Germany': {"Luge - Men's Singles": 'Gold'}},
{'Germany': {"Luge - Men's Singles": 'Silver'}},
{'Italy': {"Luge - Men's Singles": 'Bronze'}}]
你想要
['Germany': {"Luge - Men's Singles": ['Gold', 'Silver'],
"Luge - Women's Singles": ['Gold', 'Bronze']},
'Italy': {"Luge - Men's Singles": ['Bronze']}]
,给定
[{'Germany': {"Luge - Women's Singles": 'Gold'}},
{'Austria': {"Luge - Women's Singles": 'Silver'}},
{'Germany': {"Luge - Women's Singles": 'Bronze'}}]
你想要
['Germany': {"Luge - Women's Singles": ['Gold', 'Bronze']},
'Austria': {"Luge - Women's Singles": ['Silver']}]
等等。我觉得这是对问题最可能的理解。
下面的代码可以做到这一点:
from collections import defaultdict
merged = defaultdict(lambda: defaultdict(list))
for d in list_of_dicts:
for k in d:
for competition, medal in d[k].iteritems():
merged[k][competition].append(medal)
运行这个代码处理上面显示的第一个列表,你会得到
defaultdict(<function <lambda> at 0x1907db0>,
{'Italy': defaultdict(<type 'list'>, {"Luge - Men's Singles": ['Bronze']}),
'Germany': defaultdict(<type 'list'>, {"Luge - Men's Singles": ['Gold', 'Silver']})})
2) 第二种可能性是,问题中的数据是一个单一的列表,里面包含3个列表,每个列表里都有字典。我认为这不是原问题的意思,但因为我已经写好了处理这种情况的代码,所以在这里分享一下 :)
from collections import defaultdict
merged = defaultdict(lambda: defaultdict(list))
for L in listoflistsofdicts:
for d in L:
for k in d:
for competition, medal in d[k].iteritems():
merged[k][competition].append(medal)
运行上面的代码处理问题中显示的列表(加上必要的逗号),你会得到:
defaultdict(<function <lambda> at 0x1904b70>,
{'Italy': defaultdict(<type 'list'>, {"Luge - Men's Singles": ['Bronze']}),
'Austria': defaultdict(<type 'list'>, {'Luge - Doubles': ['Gold'],
"Luge - Women's Singles": ['Silver']}),
'Latvia': defaultdict(<type 'list'>, {'Luge - Doubles': ['Silver']}),
'Germany': defaultdict(<type 'list'>, {'Luge - Doubles': ['Bronze'],
"Luge - Men's Singles": ['Gold', 'Silver'],
"Luge - Women's Singles": ['Gold', 'Bronze']})
})
请注意,这两段代码都没有对奖牌类型进行排序(也就是说,你可能会得到['金牌', '银牌']或['银牌', '金牌'])。
当然,如果你得到的是像解决方案1)中那样的分开的列表,但需要将它们合并,只需把它们都放在一个列表中,然后使用解决方案2)即可。