2013-05-25 15 views
7

Szukam najbardziej wydajnego i pytonowego (głównie wydajnego) sposobu aktualizowania słownika, ale zachowaj stare wartości, jeśli obecny klucz jest obecny. Na przykład ...Aktualizowanie słownika Pythona podczas dodawania do istniejących kluczy?

myDict1 = {'1': ('3', '2'), '3': ('2', '1'), '2': ('3', '1')} 
myDict2 = {'4': ('5', '2'), '5': ('2', '4'), '2': ('5', '4')} 

myDict1.update(myDict2) gives me the following.... 

{'1': ('3', '2'), '3': ('2', '1'), '2': ('5', '4'), '5': ('2', '4'), '4': ('5', '2')} 

zawiadomienie jak istnieje klucz „2” w obu słowników i używane mieć wartości („3”, „1”), ale teraz ma wartości z to klucz w myDict2 (” 5 ',' 4 ')?

Czy istnieje sposób na skuteczną aktualizację słownika, tak aby klucz "2" kończył się wartościami ("3", "1", "5", "4")? #W żaden konkretny porządek

z góry dzięki

+2

Nie, nie ma prostego sposobu na zrobienie tego. Musisz powtarzać klucze i scalać wartości. – iurisilvio

+0

Cóż, to niefortunne, dziękuję za odpowiedź. – Ogen

+0

Wygląda na to, że reprezentujesz wykres z listą sąsiedztwa ... A co jeśli "2" :("3", "1") "i" 2 ":(" 5 "," 3 ") 'są połączone? Czy wynik będzie miał podwójne "3" na liście? – Billiska

Odpowiedz

9

myślę, że najbardziej skuteczny sposób, aby zrobić to byłoby coś takiego:

for k, v in myDict2.iteritems(): 
    myDict1[k] = myDict1.get(k,()) + v 

Ale nie jest update ekwiwalent za to, czego szukasz do zrobienia, niestety .

+0

Spróbuję teraz tej metody i zobaczę, czy potrafi obsłużyć bardzo duże słowniki i wrócić do ciebie. Dzięki za odpowiedź – Ogen

+0

@Clay Zaktualizowałem mój Odpowiedź taka, że ​​masz mniej iteracji ogólnej, może warto wypróbować moje nowe rozwiązanie, jednak w pewnym momencie przetwarzanie dużej ilości danych zajmie dużo czasu. –

+0

Dzięki za odpowiedź, myślę, że pójdę z tym – Ogen

0

Nie istnieje żaden prosty sposób zrobić to obawiam się.

Najlepszy sposób to prawdopodobnie iterowanie i łączenie. Coś jak:

for key in myDict1.iterkeys(): 
    # Thank you to user2246674 and Nolen Royalty to help me optimise this in their comments 
    if key in myDict2: 
     myDict2[key] = myDict2[key] + myDict1[key] 
    else: 
     myDict2[key] = myDict1[key] 
+0

Dzięki za odpowiedź, twoja odpowiedź działa jak czar, ale Mam słownik z kluczami 100 000+ i po prostu trwa to zbyt długo, dlatego szukałem skutecznej metody na miejscu. – Ogen

+0

Tak, przepraszam - właśnie próbowałam z 200 000 kluczy i masz rację. Trwa chwilę! Przepraszam :-( – Ewan

+0

dobry punkt - zmienię moją odpowiedź – Ewan

3

Może defaultdict pomogłoby

from collections import defaultdict 
myDict0= {'1': ('3', '2'), '3': ('2', '1'), '2': ('3', '1')} 
myDict2 = {'4': ('5', '2'), '5': ('2', '4'), '2': ('5', '4')} 
myDict1 = defaultdict(list) 
for (key, value) in myDict0.iteritems(): 
    myDict1[key].extend(value) 

for (key, value) in myDict2.iteritems(): 
    myDict1[key].extend(value) 

print myDict1 
defaultdict(<type 'list'>, {'1': ['3', '2'], '3': ['2', '1'], '2': ['3', '1', '5', '4'], '5': ['2', '4'], '4': ['5', '2']}) 
3

Najszybszym sposobem scalania dużych słowników jest wprowadzenie pośredniego obiekt, który zachowuje się jak gdyby dicts są łączone bez faktycznego ich łączenia (patrz @Raymond Hettinger's answer):

from collections import ChainMap 

class MergedMap(ChainMap): 
    def __getitem__(self, key): 
     result = [] 
     found = False 
     for mapping in self.maps: 
      try: 
       result.extend(mapping[key]) 
       found = True 
      except KeyError: 
       pass 
     return result if found else self.__missing__(key) 

merged = MergedMap(myDict1, myDict2) 

To, czy ma zastosowanie, zależy od tego, jak chcesz później użyć połączonego dyktowania.

Używa collections.ChainMap z Python 3.3+ dla wygody, aby zapewnić pełny interfejs MutableMapping; można implementować tylko części używane w starszych wersjach Pythona.

Powiązane problemy