如何在Python中合并列表中的嵌套字典?

1 投票
2 回答
835 浏览
提问于 2025-04-15 21:38

比如说,如果我得到了这样的结果:

[{'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 个回答

4
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)。

编辑:看了下示例代码,发现对于字典的列表的列表来说,语法是无效的(缺少逗号),所以我也展示了如何处理这个问题。

1

(抱歉,我其实是想在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)即可。

撰写回答