Open In App

Python – Nested Dictionary Subset

Last Updated : 10 Apr, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given a Nested Dictionary, test if another dictionary is a subset.

Examples:

Input : test_dict = {"gfg": 12, 'best' : {1 : 3, 4 : 3, 'geeks' : {8 : 7}}}, sub_dict = {8 : 7} 
Output : True 
Explanation : Required Nested dictionary present in Dictionary.
Input : test_dict = {"gfg": 12, 'best' : {1 : 3, 4 : 3, 'geeks' : {8 : 7}}}, sub_dict = {9 : 7} 
Output : False 
Explanation : Nested dictionary not present in Dictionary. 

Method 1: Using all() + any() + isinstance() + recursion

In this, We check for subset at each nesting using function, and check for all the keys matching using all(), any() is used for the utility to test for any nested possible subset matching the tested subset on the test dictionary. Each nesting is tested using recursion.

Python3




# Python3 code to demonstrate working of
# Nested Dictionary Subset Python
# Using all() + any() + isinstance() + recursion
 
 
def check_eq(mast_dict, subdict):
    if not isinstance(mast_dict, (dict, list)):
        return mast_dict == subdict
    if isinstance(mast_dict, list):
 
        # check for nesting dictionaries in list
        return all(check_eq(x, y) for x, y in zip(mast_dict, subdict))
 
    # check for all keys
    return all(mast_dict.get(idx) == subdict[idx] or check_eq(mast_dict.get(idx), subdict[idx]) for idx in subdict)
 
 
def is_subset(mast_dict, subdict):
    if isinstance(mast_dict, list):
 
        # any matching dictionary in list
        return any(is_subset(idx, subdict) for idx in mast_dict)
 
    # any matching nested dictionary
    return check_eq(mast_dict, subdict) or (isinstance(mast_dict, dict) and any(is_subset(y, subdict) for y in mast_dict.values()))
 
 
# initializing dictionary
test_dict = {"gfg": 12, 'best': {1: 3, 4: 3, 'geeks': {8: 7}}, 'cs': 7}
 
# printing original dictionary
print("The original dictionary is : " + str(test_dict))
 
# initializing subset dict
sub_dict = {8: 7}
 
# calling func
res = is_subset(test_dict, sub_dict)
 
# printing result
print("Is dictionary subset : " + str(res))


Output:

The original dictionary is : {‘gfg’: 12, ‘best’: {1: 3, 4: 3, ‘geeks’: {8: 7}}, ‘cs’: 7} Is dictionary subset : True

Time complexity: O(N), where N is the number of elements in the master dictionary.
Auxiliary space: O(N), as it creates multiple recursive function calls and temporary dictionaries and lists during the search. 

Method 2: Using set() method

Another approach to solving this problem is by converting the nested dictionaries into sets of tuples and then checking if the subset is present in the master dictionary using the set.issubset() method.

Step-by-step approach ;

  • Define a function nested_dict_to_set(d) that takes a dictionary d as input.
    • Check if the input dictionary d is an instance of the dictionary type using the isinstance() function.
    • If d is an instance of dictionary, iterate over the key-value pairs in d using the items() method.
    • For each key-value pair in d, apply the nested_dict_to_set() function recursively to the value, and create a tuple containing the key and the result of the recursive call.
    • If d is an instance of a list, apply the nested_dict_to_set() function recursively to each item in the list using a list comprehension.
    • If d is neither a dictionary nor a list, return d as is.
  • Define a function is_subset(mast_dict, subdict) that takes two dictionaries mast_dict and subdict as input.
    Inside the is_subset() function, call the nested_dict_to_set() function on both mast_dict and subdict to convert them into sets of tuples.
    • Use the all() function to check if all the items in the subdict set are present in the mast_dict set.
    • Return the result of the all() function.
  • Initialize a dictionary test_dict with some nested dictionaries and values.
  • Print the original dictionary test_dict.
  • Initialize a subset dictionary sub_dict.
  • Call the is_subset() function with test_dict and sub_dict as arguments and store the result in the res variable.
  • Print the result of the is_subset() function call.

Python3




def nested_dict_to_set(d):
    if isinstance(d, dict):
        return [(k, nested_dict_to_set(v)) for k, v in d.items()]
    elif isinstance(d, list):
        return [nested_dict_to_set(item) for item in d]
    else:
        return d
 
def is_subset(mast_dict, subdict):
    return all(item in nested_dict_to_set(mast_dict) for item in nested_dict_to_set(subdict))
 
# initializing dictionary
test_dict = {"gfg": 12, 'best': {1: 3, 4: 3, 'geeks': {8: 7}}, 'cs': 7}
 
# printing original dictionary
print("The original dictionary is : " + str(test_dict))
 
# initializing subset dict
sub_dict = {8: 7}
 
# calling func
res = is_subset(test_dict, sub_dict)
 
# printing result
print("Is dictionary subset : " + str(res))


Output

The original dictionary is : {'gfg': 12, 'best': {1: 3, 4: 3, 'geeks': {8: 7}}, 'cs': 7}
Is dictionary subset : False

Time complexity: O(n), where n is the total number of elements in the input dictionaries. 
Auxiliary space: O(n), where n is the total number of elements in the input dictionary. 

Method 3: Naive (using recursion and iteration in a single function)

Here we will be checking if the sub_dict is a subset of the master_dict.

Approach:

  1. Create a function called is_subset_dict that takes two arguments master_dict and sub_dict.
  2. Check if the sub_dict is empty, if it is empty, then return True because an empty dictionary is always a subset of any dictionary.
  3. Iterate over the keys and values of the sub_dict, and for each key-value pair:
    • a. Check if the key exists in the master_dict.
      b. If the key exists, check if the value is a dictionary or not. If it is a dictionary, then call the is_subset_dict function recursively with the corresponding sub-dictionaries.
      c. If the value is not a dictionary, compare the values of the sub_dict and master_dict.
      d. If the value is not present in the master_dict, then return False.
      e. If all the values in the sub_dict are present in the master_dict, then return True.

Python3




def is_subset_dict(dict1, dict2):
    # Convert keys of both dictionaries into sets
    dict1_keys = set(dict1.keys())
    dict2_keys = set(dict2.keys())
     
    # Take intersection of key sets
    intersection = dict1_keys.intersection(dict2_keys)
     
    # Check if the intersection is equal to dict2's key set
    if intersection == dict2_keys:
         
        # Check if the values of dict2 are same as corresponding values of dict1
        for key in dict2_keys:
            if dict1[key] != dict2[key]:
                return False
         
        return True
     
    else:
        return False
 
# Example usage
dict1 = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
dict2 = {'b': 2, 'd': 4}
dict3 = {'b': 2, 'd': 5}
 
print(is_subset_dict(dict1, dict2))  # Output: True
print(is_subset_dict(dict1, dict3))  # Output: False


Output

True
False

Time complexity: O(N*M) where N is the number of keys in the sub_dict and M is the maximum depth of the sub_dict.
Auxiliary space complexity is O(M) where M is the maximum depth of the sub_dict.

Method 4: Using the all() function and dictionary comprehension

The all() function returns True if all elements of an iterable are true. We can use this function with a dictionary comprehension to check if all key-value pairs in dict2 are also present in dict1.

Approach :

  1. The function takes two dictionaries, dict1 and dict2, as inputs.
  2. The function creates a boolean variable is_subset and sets it to True.
  3. The function creates a dictionary comprehension that iterates over the key-value pairs in dict2. For each key-value pair (k, v) in dict2, the comprehension checks if k is a key in dict1 and if v is equal to the value of dict1[k].
  4. The function passes the resulting dictionary comprehension to the all() function, which returns True if all key-value pairs in dict2 are also present in dict1.
  5. If the all() function returns False, the function sets is_subset to False.
  6. The function returns the value of is_subset.

Python3




def is_subset_dict(dict1, dict2):
    is_subset = all(k in dict1 and dict1[k] == v for k, v in dict2.items())
    return is_subset
dict1 = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
dict2 = {'b': 2, 'd': 4}
dict3 = {'b': 2, 'd': 5}
 
print(is_subset_dict(dict1, dict2))  # Output: True
print(is_subset_dict(dict1, dict3))  # Output: False


Output

True
False

Time complexity: O(len(dict2)), as the dictionary comprehension and all() function iterate over the key-value pairs in dict2.
Auxiliary space: O(1), as we only create a single boolean variable is_subset.

Method 5 : use the built-in function issuperset(). 

Step-by-step approach:

Step 1: Create two sets using the items() method on the dictionaries.

Step 2: Use the issuperset() function to check if the first set is a superset of the second set.

Step 3: Return True if the first set is a superset of the second set, False otherwise.

Python3




def is_subset_dict(dict1, dict2):
    set1 = set(dict1.items())
    set2 = set(dict2.items())
    return set1.issuperset(set2)
 
dict1 = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
dict2 = {'b': 2, 'd': 4}
dict3 = {'b': 2, 'd': 5}
 
print(is_subset_dict(dict1, dict2))  # Output: True
print(is_subset_dict(dict1, dict3))  # Output: False


Output

True
False

Time complexity: O(n), where n is the number of elements in the larger dictionary.
Auxiliary space: O(n)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads