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
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
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
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
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
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.
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.