36 Stimmen

Verschmelzen von Listen von Werten eines Wörterbuchs in Python

Ich versuche, drei Wörterbücher zusammenzuführen, die alle dieselben Schlüssel haben und entweder Listen von Werten oder einzelne Werte enthalten.

one={'a': [1, 2], 'c': [5, 6], 'b': [3, 4]}
two={'a': [2.4, 3.4], 'c': [5.6, 7.6], 'b': [3.5, 4.5]}
three={'a': 1.2, 'c': 3.4, 'b': 2.3}

Was ich brauche, ist, dass alle Elemente in den Werten zu einer Liste hinzugefügt werden.

result={'a': [1, 2, 2.4, 3.4, 1.2], 'c': [5, 6, 5.6, 7.6, 3.4], 'b': [3, 4, 3.5, 4.5, 2.3]}

Ich habe mehrere Dinge ausprobiert, aber die meisten fügen die Werte in verschachtelte Listen ein. Zum Beispiel:

out=dict((k, [one[k], two.get(k), three.get(k)]) for k in one)
{'a': [[1, 2], [2.4, 3.4], 1.2], 'c': [[5, 6], [5.6, 7.6], 3.4], 'b': [[3, 4], [3.5, 4.5], 2.3]}

Ich habe versucht, es zu aktualisieren, indem ich durch die Werte iteriert habe:

out.update((k, [x for x in v]) for k,v in out.iteritems())

aber das Ergebnis war genau das gleiche. Ich habe versucht, einfach die Listen hinzuzufügen, aber weil das dritte Wörterbuch nur einen Float-Wert hat, konnte ich es nicht tun.

check=dict((k, [one[k]+two[k]+three[k]]) for k in one)

Also versuchte ich zuerst die Listen in den Werten von one und two zu addieren und dann den Wert von three anzuhängen. Das Hinzufügen der Listen hat gut funktioniert, aber dann, als ich versuchte, den Float-Wert aus dem dritten Wörterbuch anzuhängen, ging plötzlich der gesamte Wert zu 'None'

check=dict((k, [one[k]+two[k]]) for k in one)
{'a': [[1, 2, 2.4, 3.4]], 'c': [[5, 6, 5.6, 7.6]], 'b': [[3, 4, 3.5, 4.5]]}
new=dict((k, v.append(three[k])) for k,v in check.items())
{'a': None, 'c': None, 'b': None}

39voto

Martijn Pieters Punkte 953257

Als Einzeiler, mit einer Dictionary-Abbildung:

new = {key: value + two[key] + [three[key]] for key, value in one.iteritems()}

Dies erstellt neue Listen, indem die Liste aus one mit der entsprechenden Liste aus two konkateniert wird und der einzelne Wert in three in eine temporäre Liste gesetzt wird, um die Konkatenation zu erleichtern.

Oder mit einer for-Schleife, die one direkt aktualisiert:

for key, value in one.iteritems():
    value.extend(two[key])
    value.append(three[key])

Dies verwendet list.extend(), um die Original-Liste direkt mit der Liste aus two zu aktualisieren, und list.append(), um den einzelnen Wert aus three hinzuzufügen.

Wo du dich geirrt hast:

  • Dein erster Versuch erstellt eine neue Liste mit den Werten aus one, two und three verschachtelt anstatt die vorhandenen Listen zu konkatenieren. Dein Versuch, das zu bereinigen, hat nur diese verschachtelten Listen kopiert.

  • Dein zweiter Versuch hat nicht funktioniert, weil der Wert in three keine Liste ist und daher nicht konkateniert werden konnte. Ich habe eine neue Liste nur für diesen einen Wert erstellt.

  • Dein letzter Versuch hätte list.append() nicht in einer Generator-Abbildung verwenden sollen, da du den Rückgabewert dieser Methode speicherst, der immer None ist (seine Änderung wird direkt in v gespeichert und die Liste muss nicht erneut zurückgegeben werden).

Demo des ersten Ansatzes:

>>> one={'a': [1, 2], 'c': [5, 6], 'b': [3, 4]}
>>> two={'a': [2.4, 3.4], 'c': [5.6, 7.6], 'b': [3.5, 4.5]}
>>> three={'a': 1.2, 'c': 3.4, 'b': 2.3}
>>> {key: value + two[key] + [three[key]] for key, value in one.iteritems()}
{'a': [1, 2, 2.4, 3.4, 1.2], 'c': [5, 6, 5.6, 7.6, 3.4], 'b': [3, 4, 3.5, 4.5, 2.3]}

26voto

jpp Punkte 146159

Beliebige Wörterbuchnummer und Schlüssel

Die Probleme mit Ihrem Versuch werden durch die Lösung von @MartijnPieters abgedeckt.

Für eine verallgemeinerte Lösung sollten Sie in Betracht ziehen, itertools.chain zu verwenden, um mehrere Wörterbücher zu verketten. Sie können auch ein defaultdict für den allgemeineren Fall verwenden, in dem Sie nicht die gleichen Schlüssel in jedem Wörterbuch finden.

from collections import defaultdict
from itertools import chain
from operator import methodcaller

# Wörterbücher mit ungleichen Schlüsseln, Werte alle Listen zur Vereinfachung
one = {'a': [1, 2], 'c': [5, 6], 'b': [3, 4], 'e': [6.2]}
two = {'a': [2.4, 3.4], 'c': [5.6, 7.6], 'b': [3.5, 4.5], 'f': [1.3]}
three = {'a': [1.2], 'c': [3.4], 'b': [2.3], 'e': [3.1]}

# defaultdict von Listen initialisieren
dd = defaultdict(list)

# Wörterbuchelemente durchlaufen
dict_items = map(methodcaller('items'), (one, two, three))
for k, v in chain.from_iterable(dict_items):
    dd[k].extend(v)

print(dd)

# defaultdict(list,
#             {'a': [1, 2, 2.4, 3.4, 1.2],
#              'b': [3, 4, 3.5, 4.5, 2.3],
#              'c': [5, 6, 5.6, 7.6, 3.4],
#              'e': [6.2, 3.1],
#              'f': [1.3]})

Beachten Sie, dass defaultdict eine Unterklasse von dict ist, daher besteht in der Regel kein Bedarf, das Ergebnis in ein reguläres dict umzuwandeln.

5voto

Deoclecio Freire Punkte 109

Ein robuste Lösung. =)

def FullMergeDict(D1, D2):
  for key, value in D1.items():
    if key in D2:
      if type(value) is dict:
        FullMergeDict(D1[key], D2[key])
      else:
        if type(value) in (int, float, str):
          D1[key] = [value]
        if type(D2[key]) is list:
          D1[key].extend(D2[key])
        else:
          D1[key].append(D2[key])
  for key, value in D2.items():
    if key not in D1:
      D1[key] = value

if __name__ == '__main__':
  X = {
    'a': 'aaa',
    'c': [1,3,5,7],
    'd': 100,
    'e': {'k': 1, 'p': 'aa','t': [-1,-2]},
    'f': {'j':1}
  }
  Y = {
    'b': 'bbb',
    'd': 200,
    'e': {'k': 2, 'p': 'bb','o': [-4]},
    'c': [2,4,6],
    'g': {'v':2}
  }
  FullMergeDict(X, Y)
  exit(0)

Ergebnis:

  X = {
    'a': 'aaa',
    'b': 'bbb',
    'c': [1, 3, 5, 7, 2, 4, 6],
    'd': [100, 200],
    'e': {'k': [1, 2], 'o': [-4], 'p': ['aa', 'bb'], 't': [-1, -2]},
    'f': {'j': 1},
    'g': {'v': 2}}

1voto

Mykola Zotko Punkte 11977

Wenn Sie verschiedene Schlüssel und verschiedene Arten von Werten in Wörterbüchern haben, können Sie den folgenden Ansatz verwenden:

from collections import defaultdict, Iterable

dct1 = {'a': [1, 2]}
dct2 = {'a': [3], 'b': [5, 6]}
dct3 = {'a': 4, 'c': 7}

result = defaultdict(list)
for dct in [dct1, dct2, dct3]:
    for k, v in dct.items():
        if isinstance(v, Iterable):
            result[k].extend(v)
        else:
            result[k].append(v)

print(result)
# defaultdict(, {'a': [1, 2, 3, 4], 'b': [5, 6], 'c': [7]})

1voto

Eine Zeile Lösung (auch für Schlüssel, die nur in einem der Dictionaries vorhanden sind):

{ key:one.get(key,[])+two.get(key,[]) for key in set(list(one.keys())+list(two.keys())) }

Beispiel 1:

one = {'a': [1, 2], 'c': [5, 6], 'b': [3, 4]}
two = {'a': [2.4, 3.4], 'c': [5.6, 7.6], 'd': [3.5, 4.5]}
{ key:one.get(key,[])+two.get(key,[]) for key in set(list(one.keys())+list(two.keys())) }

Ausgabe:

{'a': [1, 2, 2.4, 3.4], 'b': [3, 4], 'c': [5, 6, 5.6, 7.6], 'd': [3.5, 4.5]}

Beispiel 2:

x={1:['a','b','c']}
y={1:['d','e','f'],2:['g']}
{ key:x.get(key,[])+y.get(key,[]) for key in set(list(x.keys())+list(y.keys())) }

Ausgabe:

{1: ['a', 'b', 'c', 'd', 'e', 'f'], 2: ['g']}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X