merging two python dicts and keeping the max key, val in the new updated dict

后端 未结 6 719
悲哀的现实
悲哀的现实 2021-01-26 18:30

I need a method where I can merge two dicts keeping the max value when one of the keys, value are in both dicts.

dict_a maps \"A\", \"B\", \"C\" to 3, 2, 6

dict_

相关标签:
6条回答
  • 2021-01-26 19:00

    OK so this works by making a union set of all possible keys dict_a.keys() | dict_b.keys() and then using dict.get which by default returns None if the key is not present (rather than throwing an error). We then take the max (of the one which isn't None).

    def none_max(a, b):
        if a is None:
            return b
        if b is None:
            return a
        return max(a, b)
    
    def max_dict(dict_a, dict_b):
       all_keys = dict_a.keys() | dict_b.keys()
       return  {k: none_max(dict_a.get(k), dict_b.get(k)) for k in all_keys}
    

    Note that this will work with any comparable values -- many of the other answers fail for negatives or zeros.


    Example: Inputs:

    dict_a = {'a': 3, 'b': 2, 'c': 6}
    
    dict_b = {'b': 7, 'c': 4, 'd': 1}
    

    Outputs:

    max_dict(dict_a, dict_b)  # == {'b': 7, 'c': 6, 'd': 1, 'a': 3}
    
    0 讨论(0)
  • 2021-01-26 19:11

    Here is a working one liner

    from itertools import chain
    
    x = dict(a=30,b=40,c=50)
    y = dict(a=100,d=10,c=30)
    
    x = {k:max(x.get(k, 0), y.get(k, 0)) for k in set(chain(x,y))}
    
    In[83]: sorted(x.items())
    Out[83]: [('a', 100), ('b', 40), ('c', 50), ('d', 10)]
    

    This is going to work in any case, i.e for common keys it will take the max of the value otherwise the existing value from corresponding dict.

    0 讨论(0)
  • 2021-01-26 19:14

    Yet another solution:

    a = {"A":3, "B":2, "C":6}
    b = {"B":7, "C":4, "D":1}
    

    Two liner:

    b.update({k:max(a[k],b[k]) for k in a if b.get(k,'')})
    res = {**a, **b}
    

    Or if you don't want to change b:

    b_copy = dict(b)
    b_copy.update({k:max(a[k],b[k]) for k in a if b.get(k,'')})
    res = {**a, **b_copy}
    
    > {'A': 3, 'B': 7, 'C': 6, 'D': 1}
    
    0 讨论(0)
  • 2021-01-26 19:15

    If you know that all your values are non-negative (or have a clear smallest number), then this oneliner can solve your issue:

    a = dict(a=3,b=2,c=6)
    b = dict(b=7,c=4,d=1)
    merged = { k: max(a.get(k, 0), b.get(k, 0)) for k in set(a) | set(b) }
    

    Use your smallest-possible-number instead of the 0. (E. g. float('-inf') or similar.)

    0 讨论(0)
  • 2021-01-26 19:15

    What about

    {
        k:max(
            dict_a.get(k,-float('inf')),
            dict_b.get(k,-float('inf'))
        ) for k in dict_a.keys()|dict_b.keys()
    }
    

    which returns

    {'A': 3, 'D': 1, 'C': 6, 'B': 7}
    


    With

    >>> dict_a = {'A':3, 'B':2, 'C':6}
    >>> dict_b = {'B':7, 'C':4, 'D':1}
    
    0 讨论(0)
  • 2021-01-26 19:24

    Extending this so you can have any number of dictionaries in a list rather than just two:

    a = {'a': 3, 'b': 2, 'c': 6}
    b = {'b': 7, 'c': 4, 'd': 1}
    c = {'c': 1, 'd': 5, 'e': 7}
    
    all_dicts = [a,b,c]
    
    from functools import reduce
    
    all_keys = reduce((lambda x,y : x | y),[d.keys() for d in all_dicts])
    
    max_dict = { k : max(d.get(k,0) for d in all_dicts) for k in all_keys }
    
    0 讨论(0)
提交回复
热议问题