15

I'm trying to merge two dictionaries based on key value. However, I'm not able to achieve it. Below is the way I tried solving.

dict1 = {4: [741, 114, 306, 70],
         2: [77, 325, 505, 144],
         3: [937, 339, 612, 100],
         1: [52, 811, 1593, 350]}
dict2 = {1: 'A', 2: 'B', 3: 'C', 4: 'D'}

My resultant dictionary should be

output = {'D': [741, 114, 306, 70],
          'B': [77, 325, 505, 144],
          'C': [937, 339, 612, 100],
          'A': [52, 811, 1593, 350]}

My code

def mergeDictionary(dict_obj1, dict_obj2):
    dict_obj3 = {**dict_obj1, **dict_obj2}
    for key, value in dict_obj3.items():
        if key in dict_obj1 and key in dict_obj2:
               dict_obj3[key] = [value , dict_obj1[key]]
    return dict_obj3

dict_3 = mergeDictionary(dict1, dict2)

But I'm getting this as output

dict_3={4: ['D', [741, 114, 306, 70]], 2: ['B', [77, 325, 505, 144]], 3: ['C', [937, 339, 612, 100]], 1: ['A', [52, 811, 1593, 350]]}

6 Answers 6

14

Use a simple dictionary comprehension:

output = {dict2[k]: v for k,v in dict1.items()}

Output:

{'D': [741, 114, 306, 70],
 'B': [77, 325, 505, 144],
 'C': [937, 339, 612, 100],
 'A': [52, 811, 1593, 350]}
5

While the simple dictionary comprehension by @mozway is certainly the most straightforward and elegant solution, it rests on the assumption that the keys of dict1 are a subset of those of dict2. If not, you'll get a KeyError.

If that assumption does not hold, you'll need to decide for yourself, how you want to deal with the case when a key in dict1 is not present in dict2. A few options come to mind:

  1. Simply discard that key, if it is missing in the second dictionary.
  2. Use some (hashable) default/placeholder key, like None for instance.
  3. Raise a more descriptive error to tell the caller what exactly was wrong.
  4. Collect the values for which no key was found in the second dictionary in some separate data structure.

For example, here is a generic function that uses option 1:

from collections.abc import Hashable, Mapping
from typing import TypeVar

KeyShared = TypeVar("KeyShared", bound=Hashable)
KeyOut = TypeVar("KeyOut", bound=Hashable)
Value = TypeVar("Value")

def merge(
    keys_map: Mapping[KeyShared, KeyOut],
    values_map: Mapping[KeyShared, Value],
) -> dict[KeyOut, Value]:
    output = {}
    for key, value in values_map.items():
        if key in keys_map:
            output[keys_map[key]] = value
    return output

Test:

if __name__ == "__main__":
    dict1 = {
        5: [1, 2, 3],
        4: [741, 114],
        2: [77, 325],
        3: [937, 339],
        1: [52, 811],
    }
    dict2 = {1: 'A', 2: 'B', 3: 'C', 4: 'D'}
    print(merge(dict2, dict1))

Output:

{'D': [741, 114], 'B': [77, 325], 'C': [937, 339], 'A': [52, 811]}

As a bonus, because of the type variables, static type checkers will correctly infer the specific type of dictionary returned by it based on the argument types. I.e. with the dict1 and dict2 from the example, the type of the merged dictionary will be inferred as dict[str, list[int]].

Incidentally, if you choose option 1, you can still write this as a nice little dictionary comprehension, just with the added condition:

output = {dict2[key]: value for key, value in dict1.items() if key in dict2}

The result is the same.

4

You can use dict.update():

def mergeDictionary(dict_obj1, dict_obj2):
    dict_obj3 = dict()
    for key, val in dict_obj1.items():
       dict_obj3.update({dict_obj2[key]: val})
    return dict_obj3

or:

def mergeDictionary(dict_obj1, dict_obj2):
    dict_obj3 = dict()
    for key, val in dict_obj1.items():
       dict_obj3[dict_obj2[key]] = val
    return dict_obj3
2

The error seems to be in this line:

dict_obj3[key] = [value , dict_obj1[key]]

You want to use the value as criteria to assign an element to your dictionary, as such:

dict_obj3[value] = dict_obj1[key]

This code should do the trick:

dict1={4: [741, 114, 306, 70], 2: [77, 325, 505, 144], 3: [937, 339, 612, 100], 1: [52, 811, 1593, 350]}
dict2={1: 'A', 2: 'B', 3: 'C', 4: 'D'}

# My resultant dictionary should be 
# output={D: [741, 114, 306, 70], B: [77, 325, 505, 144], C: [937, 339, 612, 100], A: [52, 811, 1593, 350]}


# My code

def mergeDictionary(dict_obj1, dict_obj2):
    dict_obj3 = {} # {**dict_obj1, **dict_obj2}
    for key, value in dict_obj2.items():
            dict_obj3[value] = dict_obj1[key]
    return dict_obj3

dict_3 = mergeDictionary(dict1, dict2)
print(dict_3)
0

If you're using pandas in your project already, it has a method that does precisely what you're asking for:

import pandas as pd

df1 = pd.DataFrame(dict1)
df1.rename(columns=dict2)
df1

enter image description here

Otherwise it might not be worth the while.

2
  • 1
    Sure, a sledgehammer can be used to crack a nut. Commented Nov 28, 2022 at 11:33
  • @DaniilFajnberg :D My preposition was that he already had dict1 it in pandas. But he would probably mention it in the question. Commented Nov 28, 2022 at 16:54
0

use a list comprehension to map the new key into the resulting dictionary

dict1 = {4: [741, 114, 306, 70],
         2: [77, 325, 505, 144],
         3: [937, 339, 612, 100],
         1: [52, 811, 1593, 350]}
dict2 = {1: 'A', 2: 'B', 3: 'C', 4: 'D'}

dict3={dict2[key]: dict1[key] for key in dict2}
print(dict3)

output

{'A': [52, 811, 1593, 350], 'B': [77, 325, 505, 144], 'C': [937, 339, 612, 100], 'D': [741, 114, 306, 70]}

Not the answer you're looking for? Browse other questions tagged or ask your own question.