Python

[Python] Dictionary 병합

비번변경 2022. 10. 7. 17:31

개요

서로 다른 Dictionary 두 개를 병합하고자 한다. 두 Dictionary에는 중복된 키가 있을 수도 있고 없을 수도 있다.

몇 가지 방법을 정리해둔다.

 

 

dictionary.update(iterable)

update 함수는 호출한 Dictionary를 변경하는 함수로, 매개변수로 전달받은 Dictionary 또는 iterable 한 객체를 추가한다.

key가 중복되는 경우 매개변수로 전달된 값으로 갱신된다.

 

예시 ) Dictionary

x = {"spam": 1, "eggs": 2, "cheese": 3}
y = {"cheese": "cheddar", "aardvark": "Ethel"}

x.update(y)

Dictionary update

 

예시 ) tuple iterable

tuple 데이터에서 먼저 나열된 값이 key가 된다.

x = {"spam": 1, "eggs": 2, "cheese": 3}
x.update([('cheese', 'cheddar'), ('aardvark', 'Ethel')])

tuple update

 

예시 ) kwargs update

kwargs 형식으로 전달할 수도 있다.

x = {"spam": 1, "eggs": 2, "cheese": 3}
x.update(cheese='cheddar', aardvark='Ethel')

kwargs update

 

+ Dictionary Copy

만약 원본 Dictionary 데이터를 휴지하고 싶다면, 병합 결과를 저장할 Dictionary로 원본 Dictionary를 copy 한 뒤 update 하면 된다.

x = {"spam": 1, "eggs": 2, "cheese": 3}
y = {"cheese": "cheddar", "aardvark": "Ethel"}

z = x.copy()
z.update(y)
print(x)
print(z)

원본 데이터 유지

 

 

새 Dictionary에 초기화

dict() 생성자를 이용하는 방법으로 매개변수로 병합할 dictionary를 전달할 수 있다. 병합된 Dictionary는 새 Dictionary에 저장되므로 기존 데이터를 유지할 수 있다. 

x = {"spam": 1, "eggs": 2, "cheese": 3}
y = {"cheese": "cheddar", "aardvark": "Ethel"}

z = dict(x, **y)
print(z)

이 방법은 빠르고 효율적이지만 읽기가 어렵고 의도된 용법이 아니라는 단점이 있다. 또한 key가 문자열이 아닌 경우에는 동작하지 않는다.

즉, 권장하지 않는다.

 

 

Python 3.5 이상에서 제안된 구문은 다음과 같다

x = {"spam": 1, "eggs": 2, "cheese": 3}
y = {"cheese": "cheddar", "aardvark": "Ethel"}

z = {**x, **y}
print(z)

 

Python 3.9 이상에서 사용할 수 있는 구문은 다음과 같다.

x = {"spam": 1, "eggs": 2, "cheese": 3}
y = {"cheese": "cheddar", "aardvark": "Ethel"}

z = x | y
print(x)

 

세 방법 모두 중복 키가 있으면 나중에 전달된 Dictionary의 값으로 업데이트된다.

중복 키의 경우

 

 

|=

Python 3.9에서 도입된 연산자로 update 함수와 동일하게 동작한다.

x = {"spam": 1, "eggs": 2, "cheese": 3}
y = {"cheese": "cheddar", "aardvark": "Ethel"}
x |= y
print(x)

|=

 

 

임의 개수의 Dictionary 병합

임의 개수의 사전을 병합할 때는 다음과 같음 함수를 선언하여 사용할 수 있다.

def merge_dicts(*dict_args):
    """
    Given any number of dictionaries, shallow copy and merge into a new dict,
    precedence goes to key-value pairs in latter dictionaries.
    """
    result = {}
    for dictionary in dict_args:
        result.update(dictionary)
    return result
    
    
z = merge_dicts(a, b, c, d, e, f, g)

나중에 전달되는 f, g 등의 Dictionary가 먼저 전달되는 a, b 등의 Dictionary보다 우선된다.

 

 

기타

아래 방식은 성능은 떨어지지만 적절하게 동작하는 구문이다.

 

dict comprehension

python 2.7 이상

x = {"spam": 1, "eggs": 2, "cheese": 3}
y = {"cheese": "cheddar", "aardvark": "Ethel"}

z = {k: v for d in (x, y) for k, v in d.items()}
print(z)

 

Generator 이용

python 2

x = {"spam": 1, "eggs": 2, "cheese": 3}
y = {"cheese": "cheddar", "aardvark": "Ethel"}

z = dict((k, v) for d in (x, y) for k, v in d.items())
print(z)

 

itertools.chain

from itertools import chain

x = {"spam": 1, "eggs": 2, "cheese": 3}
y = {"cheese": "cheddar", "aardvark": "Ethel"}

z = dict(chain(x.items(), y.items()))
print(z)

 

 

참고 문서

https://codechacha.com/ko/python-merge-two-dict/

https://python-reference.readthedocs.io/en/latest/docs/dict/update.html

https://novdov.github.io/python/2020/03/08/python39-new-features-dict/

https://stackoverflow.com/questions/38987/how-do-i-merge-two-dictionaries-in-a-single-expression