2010-11-20 15 views
6

Posiadam kilka słowników z różnymi i powszechnymi kluczami oraz różne i wspólne klucze w zagnieżdżonym słowniku. Poniżej znajduje się uproszczony przykład, rzeczywiste słowniki mają tysiące kluczy.Scal zagnieżdżone słowniki za pomocą zagnieżdżonych klawiszy?

{1:{"Title":"Chrome","Author":"Google","URL":"http://"}} 
{1:{"Title":"Chrome","Author":"Google","Version":"7.0.577.0"}} 
{2:{"Title":"Python","Version":"2.5"}} 

Który chciałbym scalić w jeden słownik.

{1:{"Title":"Chrome","Author":"Google","URL":"http://","Version":"7.0.577.0"}, 
2:{"Title":"Python","Version":"2.5"}} 

mogę iteracyjne nad obu słowników, porównaj klucze i update zagnieżdżonych słowniki, ale nie ma chyba bardziej wydajne, albo pythonic, sposobem, aby to zrobić. Jeśli nie, co jest najbardziej wydajne?

Wartości zagnieżdżonego słownika nie muszą być porównywane.

+0

Jeśli naprawdę mapowanie klawiszy kolejnych liczb całkowitych, nie byłoby bardziej sensowne, aby produkować lista jako wyjście? –

+0

Wiele dyskusji i wskazówek tutaj: http://stackoverflow.com/questions/38987/how-can-i-merge-two-python-dictionaries-as-a-single-expression – mjhm

+0

Wydaje się bardzo nierealne, że każdy z "kilka słowników" zawiera dokładnie jedną parę klucz/wartość - zastanawia się, dlaczego w ogóle są słownikami, gdy prosta krotka lub lista z dwoma przedmiotami działała równie dobrze. – martineau

Odpowiedz

5
from collections import defaultdict 

mydicts = [ 
    {1:{"Title":"Chrome","Author":"Google","URL":"http://"}}, 
    {1:{"Title":"Chrome","Author":"Google","Version":"7.0.577.0"}}, 
    {2:{"Title":"Python","Version":"2.5"}}, 
] 

result = defaultdict(dict) 

for d in mydicts: 
    for k, v in d.iteritems(): 
     result[k].update(v) 

print result 

defaultdict(<type 'dict'>, 
    {1: {'Version': '7.0.577.0', 'Title': 'Chrome', 
     'URL': 'http://', 'Author': 'Google'}, 
    2: {'Version': '2.5', 'Title': 'Python'}}) 
+0

Drobne poprawki: Drugie "na" można zastąpić przez 'k, v = next (d.iteritems())' i następną linię dedented. Niezbyt duża różnica, ale * wyglądałaby * szybciej. ;-) – martineau

+0

@martineau: byłoby również mniej przydatne: 'next()' działa tylko na pythonie 2.6+. Również sposób, w jaki napisałem, akceptuje więcej niż jeden klucz na każdym 'dyktowaniu' lub pusty' dyktować' bez dławienia lub robienia niewłaściwej rzeczy. – nosklo

+0

Dobrze, masz rację, że 'next()' nie jest dostępne przed wersją 2.6. - pisząc to, zapomniałem, że OP chce mieć rozwiązanie zgodne z V2.5. Można jednak spierać się, czy pożądane byłoby zaakceptowanie źle sformułowanego 'dyktującego' z więcej niż jednym kluczem, a na końcu, 'next()' może obsłużyć puste 'dict's bez problemu. Biorąc wszystko pod uwagę, nadal uważam, że mój komentarz jest ważną obserwacją dla tych, którzy używają co najmniej v2.6 Pythona. – martineau

2

Z Twojego przykład, wygląda jak można zrobić coś takiego:

from collections import defaultdict 
mydict = defaultdict(dict) 
for indict in listofdicts: 
    k, v = indict.popitem() 
    mydict[k].update(v)