Calculate difference in keys contained in two Python dictionaries

后端 未结 21 1277
眼角桃花
眼角桃花 2020-11-27 09:33

Suppose I have two Python dictionaries - dictA and dictB. I need to find out if there are any keys which are present in dictB but not

相关标签:
21条回答
  • 2020-11-27 09:40

    not sure whether its "fast" or not, but normally, one can do this

    dicta = {"a":1,"b":2,"c":3,"d":4}
    dictb = {"a":1,"d":2}
    for key in dicta.keys():
        if not key in dictb:
            print key
    
    0 讨论(0)
  • 2020-11-27 09:40

    If you really mean exactly what you say (that you only need to find out IF "there are any keys" in B and not in A, not WHICH ONES might those be if any), the fastest way should be:

    if any(True for k in dictB if k not in dictA): ...
    

    If you actually need to find out WHICH KEYS, if any, are in B and not in A, and not just "IF" there are such keys, then existing answers are quite appropriate (but I do suggest more precision in future questions if that's indeed what you mean;-).

    0 讨论(0)
  • 2020-11-27 09:40

    If on Python ≥ 2.7:

    # update different values in dictB
    # I would assume only dictA should be updated,
    # but the question specifies otherwise
    
    for k in dictA.viewkeys() & dictB.viewkeys():
        if dictA[k] != dictB[k]:
            dictB[k]= dictA[k]
    
    # add missing keys to dictA
    
    dictA.update( (k,dictB[k]) for k in dictB.viewkeys() - dictA.viewkeys() )
    
    0 讨论(0)
  • 2020-11-27 09:42

    My recipe of symmetric difference between two dictionaries:

    def find_dict_diffs(dict1, dict2):
        unequal_keys = []
        unequal_keys.extend(set(dict1.keys()).symmetric_difference(set(dict2.keys())))
        for k in dict1.keys():
            if dict1.get(k, 'N\A') != dict2.get(k, 'N\A'):
                unequal_keys.append(k)
        if unequal_keys:
            print 'param', 'dict1\t', 'dict2'
            for k in set(unequal_keys):
                print str(k)+'\t'+dict1.get(k, 'N\A')+'\t '+dict2.get(k, 'N\A')
        else:
            print 'Dicts are equal'
    
    dict1 = {1:'a', 2:'b', 3:'c', 4:'d', 5:'e'}
    dict2 = {1:'b', 2:'a', 3:'c', 4:'d', 6:'f'}
    
    find_dict_diffs(dict1, dict2)
    

    And result is:

    param   dict1   dict2
    1       a       b
    2       b       a
    5       e       N\A
    6       N\A     f
    
    0 讨论(0)
  • 2020-11-27 09:45

    Try this to find de intersection, the keys that is in both dictionarie, if you want the keys not found on second dictionarie, just use the not in...

    intersect = filter(lambda x, dictB=dictB.keys(): x in dictB, dictA.keys())
    
    0 讨论(0)
  • 2020-11-27 09:47

    The top answer by hughdbrown suggests using set difference, which is definitely the best approach:

    diff = set(dictb.keys()) - set(dicta.keys())
    

    The problem with this code is that it builds two lists just to create two sets, so it's wasting 4N time and 2N space. It's also a bit more complicated than it needs to be.

    Usually, this is not a big deal, but if it is:

    diff = dictb.keys() - dicta
    
    • You don't need to convert the right dict to a set; set difference takes any iterable (and a dict is an iterable of its keys).
    • You also don't need to convert the left dict to a set, because anything that complies with collections.abc.Mapping has a KeysView that acts like a Set.

    Python 2

    In Python 2, keys() returns a list of the keys, not a KeysView. So you have to ask for viewkeys() directly.

    diff = dictb.viewkeys() - dicta
    

    For dual-version 2.7/3.x code, you're hopefully using six or something similar, so you can use six.viewkeys(dictb):

    diff = six.viewkeys(dictb) - dicta
    

    In 2.4-2.6, there is no KeysView. But you can at least cut the cost from 4N to N by building your left set directly out of an iterator, instead of building a list first:

    diff = set(dictb) - dicta
    

    Items

    I have a dictA which can be the same as dictB or may have some keys missing as compared to dictB or else the value of some keys might be different

    So you really don't need to compare the keys, but the items. An ItemsView is only a Set if the values are hashable, like strings. If they are, it's easy:

    diff = dictb.items() - dicta.items()
    

    Recursive diff

    Although the question isn't directly asking for a recursive diff, some of the example values are dicts, and it appears the expected output does recursively diff them. There are already multiple answers here showing how to do that.

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