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’: {‘Lazyroar’: {‘best’ : 3}}}
key_list = [‘best’, ‘Lazyroar’]
Output : {‘Lazyroar’: {‘best’: 3}, ‘best’: 3}Input :
test_dict = {‘gfg’: {‘geek’: {‘good’ : 3}}}
key_list = [‘best’, ‘Lazyroar’]
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
# 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 }, 'Lazyroar' : 5 } # printing original dictionary print ("The original dictionary is : " + str (test_dict)) # initializing keys list key_list = [ 'best' , 'Lazyroar' ] # 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)) |
The original dictionary is : {'gfg': {'is': {'best': 3}}, 'for': {'all': 4}, 'Lazyroar': 5} The extracted values : {'best': 3, 'Lazyroar': 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.
Python3
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 }, 'Lazyroar' : 5 } # printing original dictionary print ( "The original dictionary is : " + str (test_dict)) # initializing keys list key_list = [ 'best' , 'Lazyroar' ] # 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)) |
The original dictionary is : {'gfg': {'is': {'best': 3}}, 'for': {'all': 4}, 'Lazyroar': 5} The extracted values : {'gfg': {'is': {'best': 3}}, 'Lazyroar': 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.
- Initialize an empty list ‘result‘
- Loop through each item (key, value pair) in the ‘test_dict‘
- If the current key is in the ‘key_list‘, append the (key, value) pair to the ‘result’ list.
- If the current value is a dictionary, recursively call the ‘get_vals‘ function with the current value and ‘key_list’ and append the result to the ‘result‘ list.
- Convert the ‘result‘ list to a dictionary and return it.
Python3
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 }, 'Lazyroar' : 5 } key_list = [ 'best' , 'Lazyroar' ] print ( "The original dictionary is : " + str (test_dict)) res = dict (get_vals(test_dict, key_list)) print ( "The extracted values : " + str (res)) |
The original dictionary is : {'gfg': {'is': {'best': 3}}, 'for': {'all': 4}, 'Lazyroar': 5} The extracted values : {'Lazyroar': 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:
- Create an empty dictionary result_dict to store the extracted values.
- Create an empty stack and push the given dictionary test_dict into it.
- While the stack is not empty:
a. Pop the top item from the stack.
b. If the popped item is a dictionary and contains any key from the key_list, extract the corresponding value and add it to result_dict.
c. If the popped item is a dictionary and contains any other dictionary, push those dictionaries onto the stack. - Return the result_dict.
Below is the implementation of the above approach:
Python3
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 }, 'Lazyroar' : 5 } key_list = [ 'best' , 'Lazyroar' ] res = get_vals(test_dict, key_list) print (res) |
{'Lazyroar': 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
- Create an empty queue.
- Enqueue the root node (test_dict) and an empty list to represent the path taken to reach it.
- While the queue is not empty:
- Dequeue a node and its path.
- If the node is a dictionary and not empty:
- For each key-value pair, add the key to the path and enqueue the value and the updated path.
- If the node is a leaf node and its key is in the key_list, yield the key-value pair.
- Return the result dictionary.
Python3
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 }, 'Lazyroar' : 5 } # printing original dictionary print ( "The original dictionary is : " + str (test_dict)) # initializing keys list key_list = [ 'best' , 'Lazyroar' ] # 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)) |
The original dictionary is : {'gfg': {'is': {'best': 3}}, 'for': {'all': 4}, 'Lazyroar': 5} The extracted values : {'Lazyroar': 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.