Open In App

Python – Test for empty Nested Records

Improve
Improve
Like Article
Like
Save
Share
Report

Sometimes, while working with Python dictionaries, we can have a problem in which we need to test if a particular dictionary has nested records, and all of them is empty, i.e with no key or no value in case of list. This kind of problem is quite common in data domains such as Data Science. Let’s discuss certain way in which this task can be performed.

Input : test_dict = {‘Gfg’: [], ‘geeks’: {}} 
Output : True 

Input : test_dict = {‘Gfg’: 4} 
Output : False

Method #1 : Using recursion + all() + isinstance() The combination of above functionalities can be used to solve this problem. In this, we check for all nesting using all(), recursion and isinstance() is used to test for dictionary or list. 

Python3




# Python3 code to demonstrate working of
# Test for empty Nested Records
# Using recursion + all() + isinstance
 
# Helper function
def hlper_fnc(test_dict):
    if isinstance(test_dict, dict):
        return all(hlper_fnc(sub) for _, sub in test_dict.items())
    if isinstance(test_dict, list):
        return all(hlper_fnc(sub) for sub in test_dict)
    return False
 
# initializing dictionary
test_dict = {'Gfg': [], 'is': { 'best': [], 'for': {} }, 'geeks': {}}
 
# printing original dictionary
print("The original dictionary : " + str(test_dict))
 
# Test for empty Nested Records
# Using recursion + all() + isinstance
res = hlper_fnc(test_dict)
 
# printing result
print("Is dictionary without data ? : " + str(res))


Output : 

The original dictionary : {‘is’: {‘best’: [], ‘for’: {}}, ‘geeks’: {}, ‘Gfg’: []} Is dictionary without data ? : True

The time complexity of this approach is O(n), where n is the total number of elements in the input dictionary. 

The auxiliary space complexity of this approach is also O(n), as the function call stack grows as the recursion depth increases. 

Method #2: Using recursion + a flag variable

Instead of using the built-in functions all() or any(), we can use a flag variable to keep track of whether any non-empty nested record has been found in the dictionary. If the flag variable remains False after checking all the nested records, it means the dictionary is empty.

Python3




# Helper function
def helper_func(test_dict):
    is_empty = True
    if isinstance(test_dict, dict):
        for _, sub in test_dict.items():
            if not helper_func(sub):
                is_empty = False
                break
    elif isinstance(test_dict, list):
        for sub in test_dict:
            if not helper_func(sub):
                is_empty = False
                break
    else:
        is_empty = False
    return is_empty
 
# initializing dictionary
test_dict = {'Gfg': [], 'is': { 'best': [], 'for': {} }, 'geeks': {}}
 
# printing original dictionary
print("The original dictionary : " + str(test_dict))
 
# Test for empty Nested Records
# Using recursion + a flag variable
res = helper_func(test_dict)
 
# printing result
print("Is dictionary without data ? : " + str(res))


Output

The original dictionary : {'Gfg': [], 'is': {'best': [], 'for': {}}, 'geeks': {}}
Is dictionary without data ? : True

Time complexity: O(N), where N is the number of elements in the nested dictionary..
Auxiliary space: O(N), as the function calls itself recursively for each non-empty nested record in the dictionary. 

Method #3: Using iteration with stack

Step 1: Define the function is_dict_empty that takes a dictionary as input and returns True if the dictionary is empty or contains only empty nested records, False otherwise.

Step 2: Initialize a stack with the values of the input dictionary.

Step 3: While the stack is not empty, pop a value from the stack.

Step 4: Check if the popped value is a dictionary.

Step 5: If the popped value is a dictionary and it’s not empty, extend the stack with its values.

Step 6: Check if the popped value is a list.

Step 7: If the popped value is a list and it’s not empty, extend the stack with its values.

Step 8: Check if the popped value is not empty.

Step 9: If the popped value is not empty, return False.

Step 10: If the loop completes, return True.

Step 11: Call the is_dict_empty function with the initialized dictionary as input.

Step 12: Print the result.

Python3




def is_dict_empty(d):
    stack = list(d.values())
    while stack:
        value = stack.pop()
        if isinstance(value, dict):
            if value:
                stack.extend(value.values())
        elif isinstance(value, list):
            if value:
                stack.extend(value)
        else:
            if value:
                return False
    return True
test_dict = {'Gfg': [], 'is': { 'best': [], 'for': {} }, 'geeks': {}}
 
print("The original dictionary: " + str(test_dict))
 
res = is_dict_empty(test_dict)
 
print("Is the dictionary without data? " + str(res))


Output

The original dictionary: {'Gfg': [], 'is': {'best': [], 'for': {}}, 'geeks': {}}
Is the dictionary without data? True

The time complexity of this approach is O(n), where n is the number of items in the dictionary. The auxiliary space is O(d), where d is the maximum depth of the nested records.

Method 4: Using a depth-first search algorithm. 

The idea is to traverse the dictionary recursively and keep track of the depth of each key-value pair. If a key-value pair is found at a greater depth than any previous pair, update the maximum depth. At the end, if the maximum depth is 1, then the dictionary is empty.

Step-by-step approach:

  • Define a recursive function dfs() that takes a dictionary, a depth variable depth, and max_depth as arguments.
  • In dfs(), if the current depth is greater than max_depth, update max_depth.
    • If the dictionary is empty, return True.
    • For each key-value pair in the dictionary, call dfs() with the value as the dictionary and depth+1 as the new depth.
      • If any call to dfs() returns False, return False.
  • After the loop, return True if max_depth is 1, else return False.
  • In is_dict_empty(), call dfs() with the input dictionary and return the result.

Below is the implementation of the above approach:

Python3




def is_dict_empty(test_dict):
    max_depth = 0
     
    def dfs(d, depth, max_depth):
        if depth > max_depth:
            max_depth = depth
        if not d:
            return True
        for _, v in d.items():
            if not dfs(v, depth+1, max_depth):
                return False
        return True
     
    return dfs(test_dict, 1, max_depth) if max_depth else True
 
# Time Complexity: O(N), where N is the number of key-value pairs in the dictionary.
# Space Complexity: O(H), where H is the maximum depth of the dictionary.
# Define test_dict
test_dict = {'Gfg': [], 'is': {'best': [], 'for': {}}, 'geeks': {}}
 
# Call is_dict_empty function
res = is_dict_empty(test_dict)
 
# Print the result
print("Is dictionary without data ? : " + str(res))


Output

Is dictionary without data ? : True

Time Complexity: O(N), where N is the number of key-value pairs in the dictionary. 
Auxiliary Space: O(H), where H is the maximum depth of the dictionary. 



Last Updated : 05 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads