Python: Check if one dictionary is a subset of another larger dictionary

前端 未结 16 639
轮回少年
轮回少年 2020-12-04 09:29

I\'m trying to write a custom filter method that takes an arbitrary number of kwargs and returns a list containing the elements of a database-like list that contain

相关标签:
16条回答
  • 2020-12-04 09:54

    Use this wrapper object that provides partial comparison and nice diffs:

    
    class DictMatch(dict):
        """ Partial match of a dictionary to another one """
        def __eq__(self, other: dict):
            assert isinstance(other, dict)
            return all(other[name] == value for name, value in self.items())
    
    actual_name = {'praenomen': 'Gaius', 'nomen': 'Julius', 'cognomen': 'Caesar'}
    expected_name = DictMatch({'praenomen': 'Gaius'})  # partial match
    assert expected_name == actual_name  # True
    
    0 讨论(0)
  • 2020-12-04 10:00

    Most of the answers will not work if within dict there are some arrays of other dicts, here is a solution for this:

    def d_eq(d, d1):
       if not isinstance(d, (dict, list)):
          return d == d1
       if isinstance(d, list):
          return all(d_eq(a, b) for a, b in zip(d, d1))
       return all(d.get(i) == d1[i] or d_eq(d.get(i), d1[i]) for i in d1)
    
    def is_sub(d, d1):
      if isinstance(d, list):
         return any(is_sub(i, d1) for i in d)
      return d_eq(d, d1) or (isinstance(d, dict) and any(is_sub(b, d1) for b in d.values()))
    
    print(is_sub(dct_1, dict_2))
    

    Taken from How to check if dict is subset of another complex dict

    0 讨论(0)
  • 2020-12-04 10:03

    Here is a solution that also properly recurses into lists and sets contained within the dictionary. You can also use this for lists containing dicts etc...

    def is_subset(subset, superset):
        if isinstance(subset, dict):
            return all(key in superset and is_subset(val, superset[key]) for key, val in subset.items())
    
        if isinstance(subset, list) or isinstance(subset, set):
            return all(any(is_subset(subitem, superitem) for superitem in superset) for subitem in subset)
    
        # assume that subset is a plain value if none of the above match
        return subset == superset
    
    0 讨论(0)
  • 2020-12-04 10:03

    This function works for non-hashable values. I also think that it is clear and easy to read.

    def isSubDict(subDict,dictionary):
        for key in subDict.keys():
            if (not key in dictionary) or (not subDict[key] == dictionary[key]):
                return False
        return True
    
    In [126]: isSubDict({1:2},{3:4})
    Out[126]: False
    
    In [127]: isSubDict({1:2},{1:2,3:4})
    Out[127]: True
    
    In [128]: isSubDict({1:{2:3}},{1:{2:3},3:4})
    Out[128]: True
    
    In [129]: isSubDict({1:{2:3}},{1:{2:4},3:4})
    Out[129]: False
    
    0 讨论(0)
  • 2020-12-04 10:07

    A short recursive implementation that works for nested dictionaries:

    def compare_dicts(a,b):
        if not a: return True
        if isinstance(a, dict):
            key, val = a.popitem()
            return isinstance(b, dict) and key in b and compare_dicts(val, b.pop(key)) and compare_dicts(a, b)
        return a == b
    

    This will consume the a and b dicts. If anyone knows of a good way to avoid that without resorting to partially iterative solutions as in other answers, please tell me. I would need a way to split a dict into head and tail based on a key.

    This code is more usefull as a programming exercise, and probably is a lot slower than other solutions in here that mix recursion and iteration. @Nutcracker's solution is pretty good for nested dictionaries.

    0 讨论(0)
  • 2020-12-04 10:08

    Convert to item pairs and check for containment.

    all(item in superset.items() for item in subset.items())
    

    Optimization is left as an exercise for the reader.

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