Test if dict contained in dict

后端 未结 4 1237
一向
一向 2020-12-24 11:19

Testing for equality works fine like this for python dicts:

first  = {\"one\":\"un\", \"two\":\"deux\", \"three\":\"trois\"}
second = {\"one\":\"un\", \"two\         


        
相关标签:
4条回答
  • 2020-12-24 11:52

    So, you basically want to check if one dictionary is a subset of another.

    first  = {"one":"un", "two":"deux", "three":"trois"}
    second = {"one":"un", "two":"deux", "three":"trois", "foo":"bar"}
    
    def subset_dic(subset, superset):
        return len(set(subset.items()) & set(superset.items())) == len(subset)
    
    
    print(subset_dic(first, second))
    

    Prints:

    True
    

    In case you want to abstract out the subset/superset part:

    def subset_dic(dict1, dict2):
        return len(set(dict1.items()) & set(dict2.items())) == len(min((dict1, dict2), key=len))
    

    Note: this will fail to work, if any value is a mutable object. Hence you can add an additional step (convert mutable object to immutable analog) in the function to overcome this limitation.

    0 讨论(0)
  • 2020-12-24 12:13

    You can use a dictionary view:

    # Python 2
    if first.viewitems() <= second.viewitems():
        # true only if `first` is a subset of `second`
    
    # Python 3
    if first.items() <= second.items():
        # true only if `first` is a subset of `second`
    

    Dictionary views are the standard in Python 3, in Python 2 you need to prefix the standard methods with view. They act like sets, and <= tests if one of those is a subset of (or is equal to) another.

    Demo in Python 3:

    >>> first  = {"one":"un", "two":"deux", "three":"trois"}
    >>> second = {"one":"un", "two":"deux", "three":"trois", "foo":"bar"}
    >>> first.items() <= second.items()
    True
    >>> first['four'] =  'quatre'
    >>> first.items() <= second.items()
    False
    

    This works for non-hashable values too, as the keys make the key-value pairs unique already. The documentation is a little confusing on this point, but even with mutable values (say, lists) this works:

    >>> first_mutable = {'one': ['un', 'een', 'einz'], 'two': ['deux', 'twee', 'zwei']}
    >>> second_mutable = {'one': ['un', 'een', 'einz'], 'two': ['deux', 'twee', 'zwei'], 'three': ['trois', 'drie', 'drei']}
    >>> first_mutable.items() <= second_mutable.items()
    True
    >>> first_mutable['one'].append('ichi')
    >>> first_mutable.items() <= second_mutable.items()
    False
    

    You could also use the all() function with a generator expression; use object() as a sentinel to detect missing values concisely:

    sentinel = object()
    if all(first[key] == second.get(key, sentinel) for key in first):
        # true only if `first` is a subset of `second`
    

    but this isn't as readable and expressive as using dictionary views.

    0 讨论(0)
  • 2020-12-24 12:17
    all(k in second and second[k] == v for k, v in first.items())
    

    if you know that none of the values can be None, it will simplify to:

    all(second.get(k, None) == v for k, v in first.items())
    
    0 讨论(0)
  • 2020-12-24 12:19

    # Updated Ans:

    METHOD-1: Using Dictionary Views:

    As Martijn suggested, We can use dictionary views to check this. dict.viewitems() acts as a set. We can perform various set operations on this like intersection, union etc. (Check this link.)

    first.viewitems() <= second.viewitems()
    True
    

    We check if first is less than equal to second. This evaluating to True means first is a subset of second.

    METHOD-2 Using issubset() operation of sets:

    (DISCLAIMER: This method has some redundancy and requires all values to be hashable. Method-1 is suggested to be followed to handle all cases. Thanks Martijn for the suggestions.)

    Use .items() attribute of a dictionary to get a list of (key,value) tuples and then use issubset() operation of sets.

    This will check for both the keys and the equality..

    >>> first  = {"one":"un", "two":"deux", "three":"trois"}
    >>> second = {"one":"un", "two":"deux", "three":"trois", "foo":"bar"}
    
    >>> set(first.items()).issubset(second.items())
    True
    
    0 讨论(0)
提交回复
热议问题