The functionality of union has been discussed many times. But sometimes, we can have a more complex container, in which we need to check for the intersection of lists which are in form of keys of dictionary. Let’s discuss certain ways to solve this type of problem.
Method #1: Using Loops Using loops is a naive brute force approach to perform this particular task. In this method, we check for keys present in both list. We even check for the keys completely not present in other to add its whole list value.
Python3
# Python3 code to demonstrate # Common elements Dictionary Value List # using loops # initializing dicts test_dict1 = { "Key1" : [ 1 , 3 , 4 ], "key2" : [ 4 , 5 ] } test_dict2 = { "Key1" : [ 1 , 7 , 3 ] } # printing original dicts print ( "The original dict 1 : " + str (test_dict1)) print ( "The original dict 2 : " + str (test_dict2)) # using loops # Common elements Dictionary Value List res = dict () for key in test_dict1: if key in test_dict2: res[key] = [] for val in test_dict1[key]: if val in test_dict2[key]: res[key].append(val) # print result print ( "The dicts after intersection is : " + str (res)) |
The original dict 1 : {'Key1': [1, 3, 4], 'key2': [4, 5]} The original dict 2 : {'Key1': [1, 7, 3]} The dicts after intersection is : {'Key1': [1, 3]}
Time Complexity: O(N^2)
Auxiliary Space: O(N^2)
Method #2: Using dictionary comprehension + set operations This is the one line approach to solve the similar problem and offers a compact alternative to above method. This solution processes by using the set comprehension to get the necessary elements bound together into lists using dictionary comprehension.
Python3
# Python3 code to demonstrate # Common elements Dictionary Value List # using dictionary comprehension + set operations # initializing dicts test_dict1 = { "Key1" : [ 1 , 3 , 4 ], "key2" : [ 4 , 5 ] } test_dict2 = { "Key1" : [ 1 , 7 , 3 ] } # printing original dicts print ( "The original dict 1 : " + str (test_dict1)) print ( "The original dict 2 : " + str (test_dict2)) # using dictionary comprehension + set operations # Common elements Dictionary Value List res = {key : list ( set ( set (test_dict1.get(key, [])) & set (test_dict2.get(key, [])))) for key in set (test_dict2) & set (test_dict1)} # print result print ( "The dicts after intersection is : " + str (res)) |
The original dict 1 : {'Key1': [1, 3, 4], 'key2': [4, 5]} The original dict 2 : {'Key1': [1, 7, 3]} The dicts after intersection is : {'Key1': [1, 3]}
Method #3: Using set and intersection method
This method uses the set() function to get the set of keys that are common to both test_dict1 and test_dict2. Then it loops over these common keys and creates a new dictionary res. For each key, it takes the set intersection of the corresponding value lists using the & operator and converts the resulting set to a list using the list() function. Finally, it assigns the key and the resulting list to the new dictionary res.
Python3
# Python3 code to demonstrate # Common elements Dictionary Value List # using set and intersection method # initializing dicts test_dict1 = { "Key1" : [ 1 , 3 , 4 ], "key2" : [ 4 , 5 ] } test_dict2 = { "Key1" : [ 1 , 7 , 3 ] } # printing original dicts print ( "The original dict 1 : " + str (test_dict1)) print ( "The original dict 2 : " + str (test_dict2)) # using set and intersection method # Common elements Dictionary Value List res = {} for key in set (test_dict1.keys()) & set (test_dict2.keys()): res[key] = list ( set (test_dict1[key]) & set (test_dict2[key])) # print result print ( "The dicts after intersection is : " + str (res)) |
The original dict 1 : {'Key1': [1, 3, 4], 'key2': [4, 5]} The original dict 2 : {'Key1': [1, 7, 3]} The dicts after intersection is : {'Key1': [1, 3]}
Time complexity: O(N*M), where N and M are the lengths of the value lists in the input dictionaries.
Auxiliary space: O(N+M), where N and M are the lengths of the value lists in the input dictionaries.
Method #4: Using map and filter
This method uses map and filter functions to iterate over the keys and values of test_dict1. The lambda function in map filters out the values in test_dict1 that are not present in test_dict2, while the lambda function in filter checks if the value is present in test_dict2. The result is a dictionary with the common values for each key in test_dict1 and test_dict2.
Python3
# Python3 code to demonstrate # Common elements Dictionary Value List # using map and filter test_dict1 = { "Key1" : [ 1 , 3 , 4 ], "Key2" : [ 4 , 5 ]} test_dict2 = { "Key1" : [ 1 , 7 , 3 ]} # printing original dicts print ( "The original dict 1 : " + str (test_dict1)) print ( "The original dict 2 : " + str (test_dict2)) res = dict ( map ( lambda k: (k, list ( filter ( lambda x: x in test_dict2.get(k, []), test_dict1[k]))), test_dict1)) # print result print ( "The dicts after intersection is : " + str (res)) |
The original dict 1 : {'Key1': [1, 3, 4], 'Key2': [4, 5]} The original dict 2 : {'Key1': [1, 7, 3]} The dicts after intersection is : {'Key1': [1, 3], 'Key2': []}
Time complexity: O(n*m), where n is the number of keys in test_dict1 and m is the maximum length of the value lists in both dictionaries.
Auxiliary space: O(n*m), since we are creating a new list of common elements for each key in test_dict1
Method #5: Using set and list comprehension
- Extract the values of both dictionaries using the ‘values()’ method and convert them to sets using the ‘set()’ function.
- Use set intersection operation ‘&’ to find the common elements between the two sets.
- Use list comprehension to create a new list of tuples, where each tuple contains a key from the first dictionary and a list of the common elements between the corresponding values in both dictionaries.
- Convert the list of tuples into a dictionary using the ‘dict()’ constructor.
Python3
# Python3 code to demonstrate # Common elements Dictionary Value List # using set and list comprehension # initializing dicts test_dict1 = { "Key1" : [ 1 , 3 , 4 ], "key2" : [ 4 , 5 ] } test_dict2 = { "Key1" : [ 1 , 7 , 3 ] } # printing original dicts print ( "The original dict 1 : " + str (test_dict1)) print ( "The original dict 2 : " + str (test_dict2)) # using set and list comprehension # Common elements Dictionary Value List set1 = set (val for lst in test_dict1.values() for val in lst) set2 = set (val for lst in test_dict2.values() for val in lst) common_set = set1 & set2 res = {key: [val for val in test_dict1[key] if val in common_set] for key in test_dict1 if key in test_dict2} # print result print ( "The dicts after intersection is : " + str (res)) |
The original dict 1 : {'Key1': [1, 3, 4], 'key2': [4, 5]} The original dict 2 : {'Key1': [1, 7, 3]} The dicts after intersection is : {'Key1': [1, 3]}
Time Complexity: O(n), where n is the total number of values in both dictionaries.
Auxiliary space: O(n), where n is the total number of values in both dictionaries, as we are storing all the unique values in sets and creating a new dictionary with values containing the common elements between the two input dictionaries.
Method#6: Using Recursive method.
This function takes in two dictionaries dict1 and dict2 as input and returns a new dictionary that contains the common elements of the values in both input dictionaries. The function first checks if either dictionary is empty, and if so, returns an empty dictionary. Otherwise, it pops the first key-value pair from dict1 and finds the intersection of its values with the corresponding key in dict2. Then, it makes a recursive call with the remaining key-value pairs and combines the results. Finally, the function returns the combined dictionary.
Python3
def find_common_elements(dict1, dict2): # base case: if one of the dictionaries is empty if not dict1 or not dict2: return {} # recursive case # get the first key-value pair of the first dictionary key, values = dict1.popitem() # find the intersection of the values in both dictionaries if key in dict2: common_values = list ( set (values) & set (dict2[key])) else : common_values = [] # recursive call with the remaining key-value pairs rest_common = find_common_elements(dict1, dict2) # combine the results and return if common_values: rest_common[key] = common_values return rest_common # initializing dicts test_dict1 = { "Key1" : [ 1 , 3 , 4 ], "key2" : [ 4 , 5 ] } test_dict2 = { "Key1" : [ 1 , 7 , 3 ] } # printing original dicts print ( "The original dict 1 : " + str (test_dict1)) print ( "The original dict 2 : " + str (test_dict2)) res = find_common_elements(test_dict1, test_dict2) # print result print ( "The dicts after intersection is : " + str (res)) |
The original dict 1 : {'Key1': [1, 3, 4], 'key2': [4, 5]} The original dict 2 : {'Key1': [1, 7, 3]} The dicts after intersection is : {'Key1': [1, 3]}
Time complexity:
The function makes recursive calls for each key-value pair in the first dictionary. Therefore, the time complexity is O(N), where N is the number of key-value pairs in the first dictionary.
Finding the intersection of values in both dictionaries takes O(m), where m is the size of the values list.
Overall time complexity can be expressed as O(N * m)
Space complexity:
The function creates a new dictionary to store the common elements, and this dictionary grows as the recursion progresses. Therefore, the space complexity is O(N), where N is the number of key-value pairs in the first dictionary.
Method#7: Using numpy:
Algorithm:
- Initialize the dictionaries test_dict1 and test_dict2.
- Convert the values of both the dictionaries to numpy arrays.
- Find the common values using numpy’s intersect1d() function.
- Create an empty dictionary res.
- Loop over all the keys in test_dict1.
- If the key is present in test_dict2, then find the intersection of values for this key in both the dictionaries and with the common values.
- Store the result in the res dictionary.
- Print the res dictionary.
Python3
import numpy as np # initializing dicts test_dict1 = { "Key1" : [ 1 , 3 , 4 ], "key2" : [ 4 , 5 ] } test_dict2 = { "Key1" : [ 1 , 7 , 3 ] } # converting values of both dicts to numpy arrays dict1_vals = np.concatenate( list (test_dict1.values())) dict2_vals = np.concatenate( list (test_dict2.values())) # finding common values using numpy intersection common_vals = np.intersect1d(dict1_vals, dict2_vals) # creating a dictionary of common values res = {} for key in test_dict1.keys(): if key in test_dict2: res[key] = list ( set (test_dict1[key]) & set (test_dict2[key]) & set (common_vals)) # print result print ( "The dicts after intersection is : " + str (res)) #This code is contributed by Vinay pinjala |
Output: The dicts after intersection is : {'Key1': [1, 3]}
Time Complexity:
Converting the values of both dictionaries to numpy arrays takes O(n) time, where n is the total number of values in both dictionaries.
Finding the common values using numpy’s intersect1d() function takes O(m*log(m)) time, where m is the total number of values in both dictionaries.
Looping over all the keys in test_dict1 takes O(k) time, where k is the total number of keys in test_dict1.
Finding the intersection of values for each key in both dictionaries takes O(n/k*log(n/k)) time.
The overall time complexity of the algorithm is O(n + mlog(m) + k(n/klog(n/k))) = O(nlog(n/k) + m*log(m) + k).
Auxiliary Space:
Converting the values of both dictionaries to numpy arrays requires O(n) space, where n is the total number of values in both dictionaries.
Finding the common values using numpy’s intersect1d() function requires O(m) space, where m is the total number of values in both dictionaries.
Creating an empty dictionary res requires O(1) space.
Storing the intersection of values for each key in the res dictionary requires O(n/k) space for each key.
The overall space complexity of the algorithm is O(n + m + k*n/k) = O(n + m + n) = O(n + m).