Open In App

Python – Extract selective keys’ values Including Nested Keys

Sometimes, while working with Python dictionaries, we can have a problem in which we need to extract selective keys’ values. This problem has been solved earlier, but sometimes, we can have multiple nestings and certain keys may be present in inner records. This problem caters all the nestings for extraction of keys’ values. Let’s discuss certain way in which this task can be solved.

Input
test_dict = {‘gfg’: {‘geeks’: {‘best’ : 3}}} 
key_list = [‘best’, ‘geeks’] 
Output : {‘geeks’: {‘best’: 3}, ‘best’: 3}



Input
test_dict = {‘gfg’: {‘geek’: {‘good’ : 3}}} 
key_list = [‘best’, ‘geeks’] 
Output : {} 

Method 1: Using recursion + loop + yield 
The combination of above functionalities can be used to solve this problem. In this, we perform the task of checking for key using conditional statements and check for nestings using recursion. The yield operator is used to dynamically return the key for assignment as it occurs.






# Python3 code to demonstrate working of
# Extract selective keys' values [ Including Nested Keys ]
# Using recursion + loop + yield
 
def get_vals(test_dict, key_list):
   for i, j in test_dict.items():
     if i in key_list:
        yield (i, j)
     yield from [] if not isinstance(j, dict) else get_vals(j, key_list)
 
# initializing dictionary
test_dict = {'gfg': {'is': {'best' : 3}}, 'for': {'all' : 4}, 'geeks': 5}
 
# printing original dictionary
print("The original dictionary is : " + str(test_dict))
 
# initializing keys list
key_list = ['best', 'geeks']
 
# Extract selective keys' values [ Including Nested Keys ]
# Using recursion + loop + yield
res = dict(get_vals(test_dict, key_list))
 
# printing result
print("The extracted values : " + str(res))

Output : 
The original dictionary is : {'gfg': {'is': {'best': 3}}, 'for': {'all': 4}, 'geeks': 5}
The extracted values : {'best': 3, 'geeks': 5}

 

Time Complexity: O(nlogn)
Auxiliary Space: O(n)

Method 2-uses recursion and a helper function:

we define a helper function _get_vals_helper that recursively traverses the dictionary and extracts the values corresponding to the keys in key_list. The function returns a dictionary containing the extracted values. We call this function from the main get_vals function and return its result.




def get_vals(test_dict, key_list):
    def _get_vals_helper(sub_dict):
        result = {}
        for key, val in sub_dict.items():
            if key in key_list:
                result[key] = val
            elif isinstance(val, dict):
                nested_result = _get_vals_helper(val)
                if nested_result:
                    result[key] = nested_result
        return result
 
    return _get_vals_helper(test_dict)
 
# initializing dictionary
test_dict = {'gfg': {'is': {'best' : 3}}, 'for': {'all' : 4}, 'geeks': 5}
 
# printing original dictionary
print("The original dictionary is : " + str(test_dict))
 
# initializing keys list
key_list = ['best', 'geeks']
 
# Extract selective keys' values [ Including Nested Keys ]
# Using recursion and helper function
res = get_vals(test_dict, key_list)
 
# printing result
print("The extracted values : " + str(res))

Output
The original dictionary is : {'gfg': {'is': {'best': 3}}, 'for': {'all': 4}, 'geeks': 5}
The extracted values : {'gfg': {'is': {'best': 3}}, 'geeks': 5}

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

Method 3-Using recursion and a list comprehension.




def get_vals(test_dict, key_list):
    return [(k, v) for k, v in test_dict.items() if k in key_list] + \
           [item for sub_dict in test_dict.values() if isinstance(sub_dict, dict)
            for item in get_vals(sub_dict, key_list)]
 
test_dict = {'gfg': {'is': {'best' : 3}}, 'for': {'all' : 4}, 'geeks': 5}
key_list = ['best', 'geeks']
print("The original dictionary is : " + str(test_dict))
 
res = dict(get_vals(test_dict, key_list))
print("The extracted values : " + str(res))

Output
The original dictionary is : {'gfg': {'is': {'best': 3}}, 'for': {'all': 4}, 'geeks': 5}
The extracted values : {'geeks': 5, 'best': 3}

Time Complexity: The time complexity of the function is O(n^2) where n is the number of elements in the input dictionary. This is because the function loops through each key-value pair in the dictionary and also recursively calls itself if a value is a dictionary. In the worst-case scenario, if all values are dictionaries, then the function will call itself n times for n elements in the dictionary, leading to a time complexity of O(n^2).

Auxiliary Space: The space complexity of the function is also O(n^2) in the worst-case scenario, where all values in the dictionary are dictionaries. This is because each recursive call creates a new list of (key, value) pairs to append to the ‘result’ list. Therefore, the space required for the ‘result’ list can grow up to O(n^2) with the increasing depth of recursion.

Method 4: Using a stack and iterative approach

Extracting values from a nested dictionary with given keys is by using a stack and an iterative approach.

Step-by-step approach:

Below is the implementation of the above approach:




def get_vals(test_dict, key_list):
    result_dict = {}
    stack = [test_dict]
     
    while stack:
        current_dict = stack.pop()
        for k, v in current_dict.items():
            if k in key_list:
                result_dict[k] = v
            elif isinstance(v, dict):
                stack.append(v)
     
    return result_dict
test_dict = {'gfg': {'is': {'best' : 3}}, 'for': {'all' : 4}, 'geeks': 5}
key_list = ['best', 'geeks']
 
res = get_vals(test_dict, key_list)
print(res)

Output
{'geeks': 5, 'best': 3}

Time complexity: O(n), where n is the total number of items in the input dictionary.
Auxiliary space: O(m), where m is the maximum depth of the nested dictionaries in the input.

Method 5: Using a Queue and BFS (Breadth-First Search) Approach




from collections import deque
 
def get_vals_bfs(test_dict, key_list):
    queue = deque([(test_dict, [])])
    res = {}
     
    while queue:
        node, path = queue.popleft()
        if isinstance(node, dict) and node:
            for key, value in node.items():
                queue.append((value, path + [key]))
        elif path[-1] in key_list:
            res[path[-1]] = node
             
    return res
# initializing dictionary
test_dict = {'gfg': {'is': {'best' : 3}}, 'for': {'all' : 4}, 'geeks': 5}
 
# printing original dictionary
print("The original dictionary is : " + str(test_dict))
 
# initializing keys list
key_list = ['best', 'geeks']
 
# Extract selective keys' values [ Including Nested Keys ]
# Using BFS approach
res = get_vals_bfs(test_dict, key_list)
 
# printing result
print("The extracted values : " + str(res))

Output
The original dictionary is : {'gfg': {'is': {'best': 3}}, 'for': {'all': 4}, 'geeks': 5}
The extracted values : {'geeks': 5, 'best': 3}

Time complexity: O(N), where N is the total number of elements in the dictionary.
Auxiliary space: O(N), where N is the maximum size of the queue.


Article Tags :