110 votes

Comment fusionner et sommer deux dictionnaires en Python?

J'ai un dictionnaire ci-dessous, et je veux ajouter à un autre dictionnaire avec des éléments non nécessairement distincts et fusionner ses résultats.

Y a-t-il une fonction intégrée pour cela, ou dois-je créer la mienne?

{
  '6d6e7bf221ae24e07ab90bba4452267b05db7824cd3fd1ea94b2c9a8': 6,
  '7c4a462a6ed4a3070b6d78d97c90ac230330603d24a58cafa79caf42': 7,
  '9c37bdc9f4750dd7ee2b558d6c06400c921f4d74aabd02ed5b4ddb38': 9,
  'd3abb28d5776aef6b728920b5d7ff86fa3a71521a06538d2ad59375a': 15,
  '2ca9e1f9cbcd76a5ce1772f9b59995fd32cbcffa8a3b01b5c9c8afc2': 11
}

Le nombre d'éléments dans le dictionnaire est également inconnu.

Lors de la fusion, si deux clés identiques sont rencontrées, les valeurs de ces clés doivent être additionnées au lieu d'être écrasées.

-1voto

Bartosz Foder Points 15

Si vous voulez créer un nouveau dict en tant que | utilisez :

>>> dict({'a': 1,'c': 2}, **{'c': 1})
{'a': 1, 'c': 1}

-1voto

L'approche de Scott en utilisant collections.Counter est agréable, mais elle a l'inconvénient de ne pas être utilisable avec sum; aussi le besoin de prendre en compte les valeurs négatives ou nulles est un peu contre-intuitif pour moi, alors que vous voulez simplement ajouter des valeurs composante par composante.

Je pense donc que ce serait une bonne idée d'écrire une classe personnalisée pour cela. C'était aussi l'idée de John Mutuma. Cependant, je veux ajouter ma solution :

Je crée une classe qui se comporte très similairement à un dict, passant essentiellement tous les appels de membres à la _data sous-jacente dans la méthode getatrr. Les seules deux choses qui sont différentes sont :

  1. elle a une DEFAULT_VALUE (similaire à collections.defaultdict) qui est utilisée comme valeur pour les clés inexistantes.
  2. elle implémente une méthode __add__() qui (avec la méthode __radd__()) se charge d'ajouter les dictionnaires composante par composante.

    from typing import Union, Any

    class AddableDict: DEFAULT_VALUE = 0

    def __init__(self, data: dict) -> None:
        self._data = data
    
    def __getattr__(self, attr: str) -> Any:
        return getattr(self._data, attr)
    
    def __getitem__(self, item) -> Any:
        try:
            return self._data[item]
        except KeyError:
            return self.DEFAULT_VALUE
    
    def __repr__(self):
        return self._data.__repr__()
    
    def __add__(self, other) -> "AddableDict":
        return AddableDict({
            key: self[key] + other[key]
            for key in set(self.keys()) | set(other.keys())
        })
    
    def __radd__(
        self, other: Union[int, "AddableDict"]
    ) -> "AddableDict":
        if other == 0:
            return self

De cette façon, nous pouvons ajouter deux de ces objets et des itérables de ces objets ainsi que sum :

>>> alpha = AddableDict({"a": 1})
>>> beta = AddableDict({"a": 10, "b": 5})
>>> alpha + beta
{'a': 11, 'b': 5}

>>> sum([beta]*10)
{'a': 100, 'b': 50}

À mes yeux, cette solution a l'avantage de fournir une interface simple et compréhensible pour le développeur à utiliser. Bien sûr, vous pouvez aussi hériter de dict au lieu d'utiliser la composition.

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