Как бы я слил вложенные словари в список в Python? - PullRequest
1 голос
/ 15 апреля 2010

например, если бы у меня был результат

[{'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'}}]

как бы я отсортировал это так, чтобы все события, которые выиграли Германия и так далее, могли быть под одним заголовком. то есть Германия будет Германией: Luge - Мужские одиночные игры: золото, серебро, Luge - Женские одиночные игры: золото, бронза, Luge - Двойные пары: бронза.

спасибо за любую помощь

РЕДАКТИРОВАТЬ: теперь это прямое копирование и вставка из оболочки Python, чтобы помочь путанице:

[{'Germany': {"Luge - мужская одиночка": 'Gold'}}, {'Germany': {"Luge - мужская одиночка": "Silver"}}, {'Italy': {"Luge - Мужские одиночные игры ": 'Бронза'}}] [{'Germany': {"Luge - женские знакомства": 'Gold'}}, {'Austria': {"Luge - женские знакомства": "Silver"}}, {'Germany ": {" Luge - женские знакомства ": 'Bronze'}}] [{'Austria': {'Luge - Doubles': 'Gold'}}, {'Latvia': {'Luge - Doubles': 'Silver'}}, {'Germany': {'Luge - Doubles': ' Бронзовый '}}]

извините за то, что я новичок в этом сайте. Он повторяется 3 раза по одному для каждого отдельного события, и мне было интересно, смогу ли я получить желаемое от слияния после последнего цикла?

Ответы [ 2 ]

4 голосов
/ 15 апреля 2010
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])

или если у вас просто список диктов вместо списка списков диктатов (трудно сказать из вашего Q! -), то просто

  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 голос
/ 16 апреля 2010

(Извините, я действительно имел в виду это как комментарий к ответу Алекса Мартелли, так как мой основан на его; но когда я первоначально писал, у меня не было достаточно репутации, чтобы комментировать)

Ответ Алекса на самом деле не дает ожидаемого результата. Я не имею в виду более тонкие моменты наличия списка списков диктов или отсутствие запятых между списками (подробнее об этом позже). Но оригинальный вопрос хотел, в результате, собрать все медали по стране, по конкурсу . Алекс ответит:

> '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) Показанные данные на самом деле являются тремя различными примерами, и задача состоит в том, чтобы объединить записи dict в каждом списке отдельно. То есть, учитывая

[{'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']})
    })

Обратите внимание, что оба этих кода не сортируют типы медалей (т. Е. Вы можете получить ['Gold', 'Silver'] или ['Silver', 'Gold']).

Конечно, если вы получаете отдельные списки, используемые в решении 1), но вам нужно объединить их все, просто соберите их все вместе в списке и используйте решение 2).

...