545 votes

Existe-t-il une manière pythonique de combiner deux dicts (en ajoutant des valeurs pour les clés qui apparaissent dans les deux)?

Par exemple j'ai deux dicts:

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

J'ai besoin d'une façon pythonique de «combiner» deux dictionnaires de sorte que le résultat soit:

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

C'est-à-dire: si une clé apparaît dans les deux dicts, ajoutez leurs valeurs, si elle apparaît dans une seule dict, gardez sa valeur.

910voto

Martijn Pieters Points 271458

Utilisez 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})
 

Les compteurs sont fondamentalement une sous-classe de dict , donc vous pouvez toujours faire tout le reste avec eux que vous feriez normalement avec ce type, comme parcourir leurs clés et leurs valeurs.

128voto

georg Points 52691

Une solution plus générique, qui fonctionne également pour les valeurs non numériques:

 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)])
 

ou même plus générique:

 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)])
 

Par exemple:

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

import operator
print combine_dicts(a, b, operator.mul)
 

84voto

Ashwini Chaudhary Points 94431
>>> 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 Points 702

Intro: Il y a (probablement) la meilleure des solutions. Mais vous devez le savoir et se souvenir de lui et parfois il faut espérer que votre version de Python n'est pas trop vieux ou quoi que peut être le problème.

Puis il y a le plus de "hacky " solutions". Ils sont grands et court, mais sont parfois difficiles à comprendre, à lire et à retenir.

Il est, cependant, une alternative qui consiste à essayer de réinventer la roue. - Pourquoi réinventer la roue? - En général, parce que c'est vraiment une bonne façon d'apprendre (et parfois simplement parce que le déjà-outil existant ne pas faire exactement ce que vous voulez et/ou la façon dont vous le souhaitez) et de la façon la plus simple si vous ne savez pas ou ne me souviens pas l'outil parfait pour votre problème.

Donc, je propose de réinventer la roue de l' Counter classe de l' collections module (partiellement au moins):

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}

Il y aurait probablement d'autres façon de mettre en œuvre et il existe déjà des outils pour le faire, mais c'est toujours agréable de voir comment les choses allaient se fait essentiellement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X