Welcome, guest | Sign In | My Account | Store | Cart

A very simple specialization of the dictionary that makes it possible to merge two dictionaries provided that they are compatible : if a given key is present in both dictionaries, it must be associated with the same value.

The method is_compatible_with() allows to check this compatibility.

If possible, dictionaries can then be merged with the merge() method or with the '|' operator. Moreover, '|=' is defined as syntactical sugar for the merge() method.

Python, 34 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# mergeable_dict - dict with merge() method.
#
# Author: Jerome Lovy

class mergeable_dict(dict):
    """dict with merge() method."""

    def is_compatible_with(self, other):
        for key in self:
            if key in other and self[key] != other[key]:
                return False
        return True

    def merge(self, other):
        for key in other:
            if key in self:
                if self[key] != other[key]:
                    raise ValueError
            else:
                self[key] = other[key]
        return self

    def __ior__(self, other):
        return self.merge(other)

    def __or__(self, other):
        result = mergeable_dict(self)
        for key in other:
            if key in result:
                if result[key] != other[key]:
                    raise ValueError
            else:
                result[key] = other[key]
        return result

Semantics : - The merged dictionary has all the keys (union) of the initial dictionaries. - A key that is present in both initial dictionaries must be associated with the same value : trying to merge dictionaries which possess the same key with two different values will raise an exception.

2 comments

Frank P Mora 15 years, 7 months ago  # | flag

A one liner that, I think, does the same thing

>>> d # dictionary 1
{'a': 1, 'c': 3, 'b': 2}
>
>>> e # dictionary 2 with {'c': 3} also
{'c': 3, 'e': 5, 'd': 4}
>>>
>>> # the one liner
>>> dict(tuple(set(d.items()+e.items())))
{'a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4}
>>>
>>> # a function
>>> f= lambda a,b: dict(tuple(set(a.items()+b.items())))
>>> f(d,e) # function application
{'a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4}
Jérôme Lovy (author) 15 years, 7 months ago  # | flag

Thanks, Frank.

It is worth noting though that given incompatible key/value pairs, dict will liberately take the last value provided:

>>> my_d = {'a': 1, 'c': 3, 'b': 2}
>>> my_e = {'c': 0, 'e': 5, 'd': 4}
>>> tuple(set(my_d.items()+my_e.items()))
(('a', 1), ('b', 2), ('e', 5), ('d', 4), ('c', 0), ('c', 3))
>>> dict(tuple(set(my_d.items()+my_e.items())))
{'a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4}

In my use-case, I prefer to have an exception raised.

Created by Jérôme Lovy on Sun, 31 Aug 2008 (MIT)
Python recipes (4591)
Jérôme Lovy's recipes (1)

Required Modules

  • (none specified)

Other Information and Tasks