2016-11-27 3 views
3

ich drei Wörterbücher haben:Wörterbücher in Wörterbuch von Listen Merge

dict1 = {'a': 1, 'b': 2, 'c': 3} 
dict2 = {'b': 3, 'c': 4} 
dict3 = {'c': 4, 'd': 4} 

Ich möchte Listen ‚merge‘ sie in einem Wörterbuch von

merged_dict = {'a':[1, np.nan, np.nan], 
       'b':[2, 3, np.nan], 
       'c':[3, 4, 4], 
       'd':[np.nan, np.nan, 4]} 

Es gibt Schlüssel, die in einigen Wörterbücher sind und nicht andere, die es ein wenig schmerzen machen, sie zu durchlaufen. Ich frage mich, was der sauberste Weg ist, dies zu tun.

+0

Warum kommt die 4 in der d-Taste nach den anderen Elementen in der Liste? – PeteyPii

+1

weil es nicht in den ersten beiden Wörterbüchern existiert – Chris

+0

Ich denke, Sie haben nur die Kugel beißen und über Wörterbücher und Schlüssel iterieren. Sie haben möglicherweise einmal iteriert, nur um alle Schlüssel zu sammeln. – hpaulj

Antwort

5

Wie in den Kommentaren erwähnt müssen Sie die Wörterbücher zunächst alle Schlüssel zu sammeln, iterieren, sonst gibt es keine Möglichkeit zu wissen, welche Schlüssel von jedem einzelnen dict fehlen. Dann können Sie merged_dict mit einem Diktatverständnis aufbauen.

import numpy as np 

dict1 = {'a': 1, 'b': 2, 'c': 3} 
dict2 = {'b': 3, 'c': 4} 
dict3 = {'c': 4, 'd': 4} 

all_dicts = (dict1, dict2, dict3) 

keys = {k for d in all_dicts for k in d} 
merged_dict = {k: [d.get(k, np.nan) for d in all_dicts] for k in keys} 
print(merged_dict) 

Ausgang

{'a': [1, nan, nan], 'b': [2, 3, nan], 'c': [3, 4, 4], 'd': [nan, nan, 4]} 

Sie konnte die Menge Verständnis innerhalb des dict Verständnis setzen, aber ich denke, dass der Code schwerer zu lesen macht.

merged_dict = {k: [d.get(k, np.nan) for d in all_dicts] 
    for k in {k for d in all_dicts for k in d}} 

Eigentlich, das Doppel for Schleife in dem Satz comp nicht so effizient ist. Es tut wahrscheinlich nicht viel für kleinen dicts, aber wenn die dicts groß sind, würde es effizienter sein, eine dieser Schleifen an C Geschwindigkeit zu tun mit der set.update Methode:

keys = set() 
for d in all_dicts: 
    keys.update(d.keys()) 

Dies ist wahrscheinlich noch besser:

keys = set().union(*all_dicts) 

Danke, Dan. D für diesen Vorschlag!

Hier ist noch eine weitere Möglichkeit, mit itertools:

from itertools import chain 
keys = set(chain.from_iterable(dicts)) 
+2

Sogar 'keys = set(). Union (* all_dicts)'. –

+0

@DanD. Guter Punkt! Ich bin überrascht, dass ich selbst nicht so darüber nachgedacht habe. :) Jetzt fühle ich mich versucht, einen 'Zeit'-Test zu schreiben, um all diese Variationen zu vergleichen, einschließlich Brendans ... –

2

Dies sollte es tun.

from itertools import chain 

dicts = [dict1, dict2, dict3] 
keys = set(chain(*[d.keys() for d in dicts])) 
merged_dict = {k: [d.get(k, np.nan) for d in dicts] for k in keys} 
+0

Dies ist im Grunde das gleiche wie die obige Antwort und 100% richtig, aber ein wenig weniger Erklärung, also gehe ich mit diesem, aber ich wählte dieses, da es auch korrekt ist. – Chris

3

pandas macht einen guten Job bei Wörterbücher Parsen und sie verschmelzen. Sie können so etwas tun.

Setup

import pandas as pd 

dict1 = {'a': 1, 'b': 2, 'c': 3} 
dict2 = {'b': 3, 'c': 4} 
dict3 = {'c': 4, 'd': 4} 

Lösung

df = pd.concat([pd.Series(d) for d in [dict1, dict2, dict3]], axis=1) 
df 

enter image description here

das Wörterbuch erhalten Sie suchen.

df.T.to_dict('list') 

{'a': [1.0, nan, nan], 
'b': [2.0, 3.0, nan], 
'c': [3.0, 4.0, 4.0], 
'd': [nan, nan, 4.0]} 
+0

Ich habe mich tatsächlich damit abgefunden und bin mit dieser Route gegangen, weil ich sowieso zu einem Pandas DataFrame konvertiert habe das Ende und das war für mich leichter zu lesen. Ich würde wetten, dass die andere Antwort schneller ist, also werde ich das als die ausgewählte Antwort belassen, es sei denn, das wird schneller, aber dieser Code war für mich leichter lesbar. – Chris

+0

@Chris Die andere Antwort ist schneller. Aber ich stimme zu, das ist intuitiver. – piRSquared

+0

Ich bin widersprüchlich, welche zu wählen. Wenn dieser am Ende mit mehr Stimmen endet, werde ich meine Auswahl ändern. – Chris

Verwandte Themen