Open In App
Related Articles

Python – Extract selective keys’ values Including Nested Keys

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Report issue
Report

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

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

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}, '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.

  • 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}, '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:

  • 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}, '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

  • 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}, '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.



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