값이 리스트 형태인 파이썬 딕셔너리가 있다고 가정해 보겠습니다. 이때 주어진 리스트들의 키와 값으로 만들 수 있는 모든 가능한 조합을 하나의 리스트로 생성해야 하는 경우가 자주 발생합니다.
예를 들어 요일과 시간 정보를 담은 딕셔너리가 있을 때, '화요일 오후 2시', '화요일 오전 9시'처럼 나올 수 있는 모든 경우의 수를 사전 형태의 리스트로 만드는 것이죠. 이번 글에서는 이를 구현하는 두 가지 방법을 소개합니다.
방법 1: sorted와 itertools.product 활용
itertools 모듈의 product 함수는 매개변수로 전달된 이터러블들의 데카르트 곱(Cartesian Product)을 생성합니다. 먼저 딕셔너리의 키를 정렬한 후, 두 개의 반복문을 통해 리스트에 담긴 값들로 만들 수 있는 모든 키-값 쌍의 조합을 구성합니다.
예제 코드
import itertools as it
Adict = {
"Day": ["Tue", "Wed"],
"Time": ["2pm", "9am"],
}
# Adict의 키 정렬
sorted_Adict = sorted(Adict)
# 정렬된 키를 기준으로 product 적용
res = [dict(zip(sorted_Adict, prod))
for prod in it.product(*(Adict[sorted_Adict]
for sorted_Adict in sorted_Adict))]
# 결과 출력
print(res)실행 결과
위 코드를 실행하면 다음과 같은 결과를 얻을 수 있습니다.
[{'Day': 'Tue', 'Time': '2pm'}, {'Day': 'Tue', 'Time': '9am'}, {'Day': 'Wed', 'Time': '2pm'}, {'Day': 'Wed', 'Time': '9am'}]출력 결과를 보면 각 조합이 하나의 완전한 딕셔너리로 생성되어, 키와 값이 한 번에 묶여 있는 것을 확인할 수 있습니다.
방법 2: zip 함수 활용
두 번째 방법은 zip 함수를 itertools.product와 함께 사용하는 접근법입니다. 딕셔너리의 값들을 곱집합으로 만든 뒤, zip으로 키와 값을 짝지어 새로운 딕셔너리를 구성합니다.
예제 코드
import itertools as it
Adict = {
"Day": ["Tue", "Wed"],
"Time": ["2pm", "9am"],
}
# Adict의 키 정렬
sorted_Adict = sorted(Adict)
# 정렬 후 product 적용
res = [[{key: value} for (key, value) in zip(Adict, values)]
for values in it.product(*Adict.values())]
# 결과 출력
print(res)실행 결과
위 코드를 실행하면 다음과 같은 결과가 출력됩니다.
[[{'Day': 'Tue'}, {'Time': '2pm'}], [{'Day': 'Tue'}, {'Time': '9am'}], [{'Day': 'Wed'}, {'Time': '2pm'}], [{'Day': 'Wed'}, {'Time': '9am'}]]이 방식의 결과는 각 조합이 개별 딕셔너리의 리스트 형태로 반환된다는 점에서 첫 번째 방법과 차이가 있습니다. 즉, 하나의 조합 안에서 키-값 쌍들이 분리된 딕셔너리로 담기게 됩니다.
정리
두 방법 모두 itertools.product를 핵심으로 사용하지만, 최종 결과물의 구조가 다릅니다. 키-값 쌍이 하나의 딕셔너리로 통합된 형태가 필요하다면 첫 번째 방법(dict + zip)을, 개별 딕셔너리 리스트 형태가 필요하다면 두 번째 방법을 선택하면 됩니다. 상황에 맞게 활용해 보시기 바랍니다.