파이썬에서는 리스트의 각 요소가 딕셔너리인 경우가 자주 있습니다. 여러 곳에서 수집한 데이터가 개별 딕셔너리 형태로 리스트에 담겨 있을 때, 이를 하나의 딕셔너리로 평탄화(flatten)하면 모든 키-값 쌍을 한 번에 다룰 수 있어 코드가 훨씬 깔끔해집니다.
이번 글에서는 딕셔너리 리스트를 단일 딕셔너리로 병합하는 대표적인 세 가지 방법을 예제 코드와 함께 살펴보겠습니다.
1. for 반복문과 update() 사용
가장 기본적인 방법입니다. 빈 딕셔너리를 만든 뒤 리스트를 순회하면서 각 요소를 update() 메서드로 차례대로 추가합니다. 실행 흐름이 직관적이라 초보자도 쉽게 이해할 수 있습니다.
예제
listA = [{'Mon': 2}, {'Tue': 11}, {'Wed': 3}]
# 주어진 리스트 출력
print('주어진 리스트:\n', listA)
print('객체 타입:\n', type(listA))
res = {}
for x in listA:
res.update(x)
# 결과 출력
print('평탄화된 객체:\n', res)
print('평탄화된 객체의 타입:\n', type(res))
실행 결과
위 코드를 실행하면 다음과 같은 결과가 출력됩니다.
주어진 리스트:
[{'Mon': 2}, {'Tue': 11}, {'Wed': 3}]
객체 타입:
<class 'list'>
평탄화된 객체:
{'Mon': 2, 'Tue': 11, 'Wed': 3}
평탄화된 객체의 타입:
<class 'dict'>
2. reduce() 활용
functools 모듈의 reduce() 함수를 update()와 조합하면 반복문 없이도 동일한 작업을 수행할 수 있습니다. 람다 함수는 빈 딕셔너리 {}를 초기값으로 받아 리스트의 각 요소를 순서대로 병합합니다. 이때 update()는 None을 반환하기 때문에 'or d'를 붙여 누적 딕셔너리 d를 그대로 반환하도록 처리한 부분이 핵심입니다.
예제
from functools import reduce
listA = [{'Mon': 2}, {'Tue': 11}, {'Wed': 3}]
# 주어진 리스트 출력
print('주어진 리스트:\n', listA)
print('객체 타입:\n', type(listA))
# reduce와 update 사용
res = reduce(lambda d, src: d.update(src) or d, listA, {})
# 결과 출력
print('평탄화된 객체:\n', res)
print('평탄화된 객체의 타입:\n', type(res))
실행 결과
실행 결과는 첫 번째 방법과 완전히 동일합니다.
주어진 리스트:
[{'Mon': 2}, {'Tue': 11}, {'Wed': 3}]
객체 타입:
<class 'list'>
평탄화된 객체:
{'Mon': 2, 'Tue': 11, 'Wed': 3}
평탄화된 객체의 타입:
<class 'dict'>
3. ChainMap 활용
collections 모듈의 ChainMap은 리스트의 각 딕셔너리를 하나의 뷰(view)로 묶어 줍니다. 다만 결과가 딕셔너리가 아니라 ChainMap 객체라는 점에 유의해야 하며, 일반 딕셔너리가 필요하다면 dict(res)처럼 변환해서 사용하면 됩니다.
예제
from collections import ChainMap
listA = [{'Mon': 2}, {'Tue': 11}, {'Wed': 3}]
# 주어진 리스트 출력
print('주어진 리스트:\n', listA)
print('객체 타입:\n', type(listA))
# ChainMap 사용
res = ChainMap(*listA)
# 결과 출력
print('평탄화된 객체:\n', res)
print('평탄화된 객체의 타입:\n', type(res))
실행 결과
ChainMap은 원본 딕셔너리들을 그대로 감싸는 구조이므로 출력 형태가 조금 다릅니다.
주어진 리스트:
[{'Mon': 2}, {'Tue': 11}, {'Wed': 3}]
객체 타입:
<class 'list'>
평탄화된 객체:
ChainMap({'Mon': 2}, {'Tue': 11}, {'Wed': 3})
평탄화된 객체의 타입:
<class 'collections.ChainMap'>
정리 및 참고 사항
세 가지 방법 모두 동일한 키가 여러 딕셔너리에 존재하면 나중에 병합되는 값이 앞선 값을 덮어쓴다는 점을 기억하세요. 또한 파이썬 3.5 이상에서는 딕셔너리 언패킹 문법인 {**d1, **d2, **d3}를 사용하면 한 줄로 간단하게 병합할 수 있습니다. 코드의 가독성과 용도에 맞는 방법을 선택해 사용하면 됩니다.