545 Stimmen

Gibt es eine pythonische Möglichkeit, zwei Dicts (Hinzufügen von Werten für Schlüssel, die in beiden erscheinen) zu kombinieren?

Ich habe zum Beispiel zwei Dicts:

Dict A: {'a': 1, 'b': 2, 'c': 3}
Dict B: {'b': 3, 'c': 4, 'd': 5}

Ich brauche einen pythonischen Weg der "Kombination" zwei Dicts, so dass das Ergebnis ist:

{'a': 1, 'b': 5, 'c': 7, 'd': 5}

Das heißt: Wenn ein Schlüssel in beiden Dicts vorkommt, addiere ihre Werte, wenn er nur in einem Dict vorkommt, behalte seinen Wert.

910voto

Martijn Pieters Punkte 953257

Utilice collections.Counter :

>>> from collections import Counter
>>> A = Counter({'a':1, 'b':2, 'c':3})
>>> B = Counter({'b':3, 'c':4, 'd':5})
>>> A + B
Counter({'c': 7, 'b': 5, 'd': 5, 'a': 1})

Zähler sind grundsätzlich eine Unterklasse von dict Sie können also weiterhin alles mit ihnen machen, was Sie normalerweise mit diesem Typ machen, z. B. über ihre Schlüssel und Werte iterieren.

128voto

georg Punkte 205206

Eine allgemeinere Lösung, die auch für nicht-numerische Werte funktioniert:

a = {'a': 'foo', 'b':'bar', 'c': 'baz'}
b = {'a': 'spam', 'c':'ham', 'x': 'blah'}

r = dict(a.items() + b.items() +
    [(k, a[k] + b[k]) for k in set(b) & set(a)])

oder noch allgemeiner:

def combine_dicts(a, b, op=operator.add):
    return dict(a.items() + b.items() +
        [(k, op(a[k], b[k])) for k in set(b) & set(a)])

Zum Beispiel:

>>> a = {'a': 2, 'b':3, 'c':4}
>>> b = {'a': 5, 'c':6, 'x':7}

>>> import operator
>>> print combine_dicts(a, b, operator.mul)
{'a': 10, 'x': 7, 'c': 24, 'b': 3}

84voto

Ashwini Chaudhary Punkte 231447
>>> A = {'a':1, 'b':2, 'c':3}
>>> B = {'b':3, 'c':4, 'd':5}
>>> c = {x: A.get(x, 0) + B.get(x, 0) for x in set(A).union(B)}
>>> print(c)

{'a': 1, 'c': 7, 'b': 5, 'd': 5}

48voto

jeromej Punkte 8455

Intro: Das sind die (wahrscheinlich) besten Lösungen. Aber man muss sie kennen und sich merken und manchmal muss man hoffen, dass die Python-Version nicht zu alt ist oder was auch immer das Problem sein könnte.

Und dann gibt es noch die "hakeligsten" Lösungen. Sie sind großartig und kurz, aber manchmal sind sie schwer zu verstehen, zu lesen und zu merken.

Es gibt jedoch eine Alternative, nämlich den Versuch, das Rad neu zu erfinden. - Warum das Rad neu erfinden? - Im Allgemeinen, weil es eine gute Möglichkeit ist, etwas zu lernen (und manchmal auch nur, weil das bereits vorhandene Werkzeug nicht genau das tut, was man möchte und/oder wie man es möchte), und weil es der einfachste Weg ist, wenn man das perfekte Werkzeug für sein Problem nicht kennt oder sich nicht daran erinnert.

Also schlage ich vor, das Rad der Geschichte neu zu erfinden. Counter Klasse aus der collections Modul (zumindest teilweise):

class MyDict(dict):
    def __add__(self, oth):
        r = self.copy()

        try:
            for key, val in oth.items():
                if key in r:
                    r[key] += val  # You can custom it here
                else:
                    r[key] = val
        except AttributeError:  # In case oth isn't a dict
            return NotImplemented  # The convention when a case isn't handled

        return r

a = MyDict({'a':1, 'b':2, 'c':3})
b = MyDict({'b':3, 'c':4, 'd':5})

print(a+b)  # Output {'a':1, 'b': 5, 'c': 7, 'd': 5}

Es gäbe wahrscheinlich andere Möglichkeiten, dies zu implementieren, und es gibt bereits entsprechende Tools, aber es ist immer schön, sich vorzustellen, wie die Dinge im Grunde funktionieren würden.

18voto

Mazdak Punkte 99901

Die endgültige Zusammenfassung der Counter() s ist in solchen Fällen der pythonischste Weg, aber nur, wenn sie einen positiven Wert ergibt . Hier ist ein Beispiel, und wie Sie sehen können, gibt es keine c im Ergebnis nach Negierung der c den Wert in B Wörterbuch.

In [1]: from collections import Counter

In [2]: A = Counter({'a':1, 'b':2, 'c':3})

In [3]: B = Counter({'b':3, 'c':-4, 'd':5})

In [4]: A + B
Out[4]: Counter({'d': 5, 'b': 5, 'a': 1})

Das liegt daran, dass Counter s wurden in erster Linie für die Arbeit mit positiven Ganzzahlen entwickelt, um laufende Zählungen darzustellen (negative Zählungen sind bedeutungslos). Aber um bei diesen Anwendungsfällen zu helfen, dokumentiert Python die minimalen Bereichs- und Typbeschränkungen wie folgt:

  • Die Klasse Counter selbst ist Unterklasse ohne Einschränkungen für ihre Schlüssel und Werte. Die Werte sind sollen Zahlen sein, die Zählungen darstellen, aber Sie können alles im Wertefeld speichern.
  • En most_common() m dass die Werte bestellbar sind.
  • Für Vorgänge an Ort und Stelle, wie zum Beispiel c[key] += 1 muss der Wertetyp nur Addition und Subtraktion unterstützen. So funktionieren Brüche, Gleitkommazahlen und Dezimalzahlen und negative Werte werden unterstützt. Das Gleiche gilt auch für update() y subtract() w negative Werte und Nullwerte sowohl für die Eingänge als auch für die Ausgänge zulassen.
  • Die Multiset-Methoden sind nur für Anwendungsfälle mit posi Die Eingaben können negativ oder Null sein, aber es werden nur Ausgaben mit positiven Werte werden erzeugt. Es gibt keine Typbeschränkungen, aber der Wertetyp muss Addition, Subtraktion und Vergleich unterstützen.
  • En elements() Methode erfordert ganzzahlige Werte. Sie ignoriert Nullen und negative Zählungen.

Um dieses Problem zu umgehen, können Sie nach der Summierung Ihres Zählers Counter.update um die gewünschte Ausgabe zu erhalten. Das funktioniert so dict.update() sondern fügt Zählungen hinzu, anstatt sie zu ersetzen.

In [24]: A.update(B)

In [25]: A
Out[25]: Counter({'d': 5, 'b': 5, 'a': 1, 'c': -1})

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