Python – Merge keys by values
Given a dictionary, merge the keys to map to common values.
Examples:
Input : test_dict = {1:6, 8:1, 9:3, 10:3, 12:6, 4:9, 2:3}
Output : {'1-12': 6, '2-9-10': 3, '4': 9, '8': 1}
Explanation : All the similar valued keys merged.
Input : test_dict = {1:6, 8:1, 9:3, 4:9, 2:3}
Output : {'1': 6, '2-9': 3, '4': 9, '8': 1}
Explanation : All the similar valued keys merged.
Method 1: Using defaultdict() + loop
This task is performed in 2 steps, first, group all the values and storing keys, and in 2nd step, map merged keys to common values.
Python3
from collections import defaultdict
test_dict = { 1 : 6 , 8 : 1 , 9 : 3 , 10 : 3 , 12 : 6 , 4 : 9 , 2 : 3 }
print ( "The original dictionary is : " + str (test_dict))
temp = defaultdict( list )
for key, val in sorted (test_dict.items()):
temp[val].append(key)
res = dict ()
for key in temp:
res[ '-' .join([ str (ele) for ele in temp[key]])] = key
print ( "The required result : " + str (res))
|
Output:
The original dictionary is : {1: 6, 8: 1, 9: 3, 10: 3, 12: 6, 4: 9, 2: 3}
The required result : {‘1-12’: 6, ‘2-9-10’: 3, ‘4’: 9, ‘8’: 1}
Time Complexity: O(n), where n is the length of the list test_dict
Auxiliary Space: O(n) additional space of size n is created where n is the number of elements in the res list
Method 2: Using a dictionary to store the merged keys
Approach:
- Create an empty dictionary merged_dict to store the merged keys and values.
- Loop through each key-value pair in the input dictionary test_dict.
- Check if the value already exists in the merged_dict.
- If the value does not exist, create a new key-value pair in the merged_dict with the value as the key and a list containing the key as the value.
- If the value already exists, append the key to the list of keys corresponding to that value in the merged_dict.
- Loop through each key in the merged_dict.
- If the length of the list of keys corresponding to that value is 1, replace the list with a single key.
- If the length of the list of keys corresponding to that value is greater than 1, sort the list of keys in ascending order, join them with a dash (‘-‘), and replace the list with the joined string.
- Return the merged dictionary and print the elements in the dictionary.
Python3
def merge_keys(test_dict):
merged_dict = {}
for key, value in test_dict.items():
if value not in merged_dict:
merged_dict[value] = [key]
else :
merged_dict[value].append(key)
for key in merged_dict:
if len (merged_dict[key]) = = 1 :
merged_dict[key] = merged_dict[key][ 0 ]
else :
merged_dict[key] = '-' .join([ str (k)
for k in sorted (merged_dict[key])])
return merged_dict
test_dict1 = { 1 : 6 , 8 : 1 , 9 : 3 , 10 : 3 , 12 : 6 , 4 : 9 , 2 : 3 }
merged_dict1 = merge_keys(test_dict1)
print (merged_dict1)
test_dict2 = { 1 : 6 , 8 : 1 , 9 : 3 , 4 : 9 , 2 : 3 }
merged_dict2 = merge_keys(test_dict2)
print (merged_dict2)
|
Output
{6: '1-12', 1: 8, 3: '2-9-10', 9: 4}
{6: 1, 1: 8, 3: '2-9', 9: 4}
Time complexity: O(N log(N)) due to sorting the merged keys
Auxiliary Space: O(N)
Method – Using itertools.groupby()
Steps:
- Initialize an empty dictionary res.
- Use itertools.groupby() to group the original dictionary’s items by their values, and sort them based on the values.
- Loop over the groups, and for each group, get the keys and values and merge the keys using ‘-‘.join() if there is more than one key, otherwise just use the single key.
- Assign the merged key and value to the res dictionary and print the res dictionary.
Below is the implementation of the above approach:
Python3
import itertools
from functools import reduce
test_dict = { 1 : 6 , 8 : 1 , 9 : 3 , 10 : 3 , 12 : 6 , 4 : 9 , 2 : 3 }
print ( "The original dictionary is : " + str (test_dict))
res = {}
for val, grp in itertools.groupby( sorted (test_dict.items(), key = lambda x: x[ 1 ]), lambda x: x[ 1 ]):
keys = [ str (i[ 0 ]) for i in list (grp)]
if len (keys) = = 1 :
res[keys[ 0 ]] = val
else :
res[ '-' .join(keys)] = val
print ( "The required result : " + str (res))
|
Output
The original dictionary is : {1: 6, 8: 1, 9: 3, 10: 3, 12: 6, 4: 9, 2: 3}
The required result : {'8': 1, '9-10-2': 3, '1-12': 6, '4': 9}
Time Complexity: O(n log n) (sorting the dictionary items)
Space Complexity: O(n) (creating the res dictionary and the keys list for each group)
Method – Using list comprehension
Steps:
- Create an empty dictionary res to store the result
- Using a set, extract all unique values from the given dictionary
- Using a dictionary comprehension, group the keys of the given dictionary according to their values in a dictionary temp
- Iterate over each key in temp and concatenate its values separated by ‘-‘ to create a new key in res, with the corresponding value being the original key value from temp
- Return res as the required result.
Python3
test_dict = { 1 : 6 , 8 : 1 , 9 : 3 , 10 : 3 , 12 : 6 , 4 : 9 , 2 : 3 }
print ( "The original dictionary is : " + str (test_dict))
temp = {val: [key for key, value in test_dict.items() if value = = val]
for val in set (test_dict.values())}
res = {}
for key in temp:
res[ '-' .join([ str (ele) for ele in temp[key]])] = key
print ( "The required result : " + str (res))
|
Output
The original dictionary is : {1: 6, 8: 1, 9: 3, 10: 3, 12: 6, 4: 9, 2: 3}
The required result : {'8': 1, '9-10-2': 3, '1-12': 6, '4': 9}
Time Complexity: O(n^2), where n is the length of the input dictionary. This is because the dictionary comprehension used to group the keys by values iterates over the entire input dictionary for each unique value, resulting in n^2 operations.
Auxiliary Space: O(n), where n is the length of the input dictionary. This is because we create a dictionary temp to store the keys grouped by values, which can have a maximum of n key-value pairs. The dictionary res and the set of unique values also contribute to the space complexity, but they have a maximum size of n as well. Therefore, the overall space complexity is O(n).
Method 4: Using nested for loop
Approach:
- Initialize an empty dictionary merged_dict.
- Loop through each key-value pair in the original dictionary test_dict.
- Check if the value of the current key is already in the merged_dict as a key.
- If the value is not in merged_dict, add a new key-value pair with the value as key and a list containing the key as the value.
- If the value is already in merged_dict, append the key to the existing list of keys for that value.
- Convert the list of keys for each value into a string with ‘-‘ as the separator.
- Add the new key-value pair to the res dictionary with the string of merged keys as the key and the value as the value.
- Print the resultant list.
Python3
test_dict = { 1 : 6 , 8 : 1 , 9 : 3 , 10 : 3 , 12 : 6 , 4 : 9 , 2 : 3 }
print ( "The original dictionary is : " + str (test_dict))
merged_dict = {}
res = {}
for key, value in test_dict.items():
if value in merged_dict:
merged_dict[value].append(key)
else :
merged_dict[value] = [key]
for value in merged_dict:
key_str = '-' .join([ str (key) for key in merged_dict[value]])
res[key_str] = value
print ( "The required result : " + str (res))
|
Output
The original dictionary is : {1: 6, 8: 1, 9: 3, 10: 3, 12: 6, 4: 9, 2: 3}
The required result : {'1-12': 6, '8': 1, '9-10-2': 3, '4': 9}
Time complexity: O(n), where n is the number of key-value pairs in the dictionary.
Auxiliary space: O(n), to store the merged_dict and res dictionaries.
Last Updated :
18 May, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...