Is there any pythonic way to combine two dicts (adding values for keys that appear in both)?

前端 未结 17 2283
梦毁少年i
梦毁少年i 2020-11-22 01:50

For example I have two dicts:

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

I need a pythonic way of \'comb

相关标签:
17条回答
  • 2020-11-22 02:52

    The one with no extra imports!

    Their is a pythonic standard called EAFP(Easier to Ask for Forgiveness than Permission). Below code is based on that python standard.

    # The A and B dictionaries
    A = {'a': 1, 'b': 2, 'c': 3}
    B = {'b': 3, 'c': 4, 'd': 5}
    
    # The final dictionary. Will contain the final outputs.
    newdict = {}
    
    # Make sure every key of A and B get into the final dictionary 'newdict'.
    newdict.update(A)
    newdict.update(B)
    
    # Iterate through each key of A.
    for i in A.keys():
    
        # If same key exist on B, its values from A and B will add together and
        # get included in the final dictionary 'newdict'.
        try:
            addition = A[i] + B[i]
            newdict[i] = addition
    
        # If current key does not exist in dictionary B, it will give a KeyError,
        # catch it and continue looping.
        except KeyError:
            continue
    

    EDIT: thanks to jerzyk for his improvement suggestions.

    0 讨论(0)
  • 2020-11-22 02:53

    For a more generic and extensible way check mergedict. It uses singledispatch and can merge values based on its types.

    Example:

    from mergedict import MergeDict
    
    class SumDict(MergeDict):
        @MergeDict.dispatch(int)
        def merge_int(this, other):
            return this + other
    
    d2 = SumDict({'a': 1, 'b': 'one'})
    d2.merge({'a':2, 'b': 'two'})
    
    assert d2 == {'a': 3, 'b': 'two'}
    
    0 讨论(0)
  • 2020-11-22 02:55

    What about:

    def dict_merge_and_sum( d1, d2 ):
        ret = d1
        ret.update({ k:v + d2[k] for k,v in d1.items() if k in d2 })
        ret.update({ k:v for k,v in d2.items() if k not in d1 })
        return ret
    
    A = {'a': 1, 'b': 2, 'c': 3}
    B = {'b': 3, 'c': 4, 'd': 5}
    
    print( dict_merge_and_sum( A, B ) )
    

    Output:

    {'d': 5, 'a': 1, 'c': 7, 'b': 5}
    
    0 讨论(0)
  • 2020-11-22 02:57

    This is a simple solution for merging two dictionaries where += can be applied to the values, it has to iterate over a dictionary only once

    a = {'a':1, 'b':2, 'c':3}
    
    dicts = [{'b':3, 'c':4, 'd':5},
             {'c':9, 'a':9, 'd':9}]
    
    def merge_dicts(merged,mergedfrom):
        for k,v in mergedfrom.items():
            if k in merged:
                merged[k] += v
            else:
                merged[k] = v
        return merged
    
    for dct in dicts:
        a = merge_dicts(a,dct)
    print (a)
    #{'c': 16, 'b': 5, 'd': 14, 'a': 10}
    
    0 讨论(0)
  • 2020-11-22 02:57

    The above solutions are great for the scenario where you have a small number of Counters. If you have a big list of them though, something like this is much nicer:

    from collections import Counter
    
    A = Counter({'a':1, 'b':2, 'c':3})
    B = Counter({'b':3, 'c':4, 'd':5}) 
    C = Counter({'a': 5, 'e':3})
    list_of_counts = [A, B, C]
    
    total = sum(list_of_counts, Counter())
    
    print(total)
    # Counter({'c': 7, 'a': 6, 'b': 5, 'd': 5, 'e': 3})
    

    The above solution is essentially summing the Counters by:

    total = Counter()
    for count in list_of_counts:
        total += count
    print(total)
    # Counter({'c': 7, 'a': 6, 'b': 5, 'd': 5, 'e': 3})
    

    This does the same thing but I think it always helps to see what it is effectively doing underneath.

    0 讨论(0)
提交回复
热议问题