2016-02-24 2 views
2

Это код, который я до сих пор пытаюсь проследить через три словаря, имеющих один и тот же ключ, и добавить его соответствующие значения. Если ключа нет, я бы хотел, чтобы код добавлял нуль.Слияние словарей для одного и того же ключа в Python

#!/usr/bin/env python 
import sys 
from operator import itemgetter 
import csv 
import ast 
from collections import defaultdict 

super_dic={} 
d1 = {'a':2, 'b':5, 'c':3, 'd':6} 
d2 = {'a':3, 'c':3} 
d3 = {'b':4, 'd':4} 

for d in (d1, d2, d3): 
    for key, value in d.iteritems(): 
    super_dic.setdefault(key, []).append(value) 
print super_dic 

Выход super_dic постройки:

{'a': [2, 3], 'c': [3, 3], 'b': [5, 4], 'd': [6, 4]} 

Однако, я хотел бы мой конечный результат будет:

{'a':[2, 3, 0], 'c':[3,3,0], 'b':[5,0,4],'d':[6,0,4]} 

порядок значений имеет значение

Любая помощь/обратная связь - muc ч оценили. Некоторое время борется с этим, и все подходы стараются не строить правильный мастер-словарь в конце.

* Обратите внимание, что это не дублирующий вопрос, потому что вопросы, заданные с помощью слияния словарей в Python, все игнорируют факт добавления нуля, если ключевой элемент не существует. *

+0

Вам нужны списки значений в том же порядке, что и исходные словари, или достаточно, чтобы иметь [5, 4, 0] вместо [5, 0, 4]? – Prune

+0

@ Приобрести порядок. Я добавлю, что на мой вопрос, так что его ясный – user5927494

+0

@timgeb тот, который проголосовал за +4, решил мою проблему! большое спасибо. Пошел вперед и отметил это как ответ – user5927494

ответ

5

Чтобы быть более общим, предположим, что у вас есть список словарей, называемый dicts.

>>> dicts = [d1, d2, d3] 
>>> allkeys = set(x for d in dicts for x in d.keys())  
>>> super_dic = {k:[d.get(k, 0) for d in dicts] for k in allkeys} 
>>> super_dic 
{'a': [2, 3, 0], 'c': [3, 3, 0], 'b': [5, 0, 4], 'd': [6, 0, 4]} 
+0

Очень хороший ответ. Я просто хочу добавить, что в этом случае d1 уже содержит все ключи, можно было бы пропустить создание набора «allkeys» и просто использовать d1.keys() вместо allkeys: 'super_dic = {k: [d.get (k, 0) для d в dicts] для k в d1.keys()} ' – JLT

0

Я нашел несколько (неудобный) решение:

from collections import defaultdict 

super_dic={} 
d1 = {'a':2, 'b':5, 'c':3, 'd':6} 
d2 = {'a':3, 'c':3} 
d3 = {'b':4, 'd':4} 

# Counter because it might be that there is some element only present in a later dict. 
# And we need to compare the current list lengths in each turn 
i = 0 
for d in (d1, d2, d3): 
    for key in d: 
     # It might be that a key wasn't present before so set default to [0]*i 
     super_dic.setdefault(key, [0]*i).append(d[key]) 
    # Increment i so we can compare the list lengths: 
    i += 1 
    # Append 0 for every key that wasn't appended in this turn: 
    for key in super_dic: 
     if len(super_dic[key]) < i: 
      super_dic[key].append(0) 
print(super_dic) 

{'b': [5, 0, 4], 'a': [2, 3, 0], 'd': [6, 0, 4], 'c': [3, 3, 0]} 

Объяснение находится внутри комментарии в-коде, я надеюсь, это понятно, в противном случае я буду разрабатывать их дальше. Просто прокомментируйте, если что-то неясно.

1

Я сделал бы это так. Получите все ключи в наборе, создайте defaultdict со списком. И затем перебирайте все ключи для всех словарей.

all_keys = set(d1).union(d2).union(d3) 

merged_dict = defaultdict(list) 
for d in (d1,d2,d3): 
    for key in all_keys: 
     merged_dict[key] += d.get(key, 0), 

print merged_dict 
Смежные вопросы