이 글에서는 Python에서 두 개의 딕셔너리 리스트를 비교하는 방법과, 두 리스트 사이의 차이점을 출력하는 방법까지 자세히 알아봅니다.
여기서 소개하는 비교 방식은 딕셔너리의 키(key)와 값(value)을 모두 대상으로 비교합니다.
또한, Python에서 두 딕셔너리 리스트를 비교할 때는 요소의 순서는 중요하지 않습니다. 즉, 키-값 쌍이 동일하기만 하면 순서가 달라도 같은 것으로 판단됩니다.
Python에서 딕셔너리 리스트 비교하기
if __name__ == '__main__':
list_1 = [
{'id': '123-abc', 'name': 'Mike', 'age': 40},
{'name': 'John', 'age': 34, 'id': '123-efg'},
{'age': 32, 'id': '123-xyz', 'name': 'Aly'}
]
list_2 = [
{'name': 'Mike', 'id': '123-abc', 'age': 40},
{'id': '123-efg', 'age': 34, 'name': 'John'},
{'id': '123-xyz', 'name': 'Aly', 'age': 32}
]
assert [i for i in list_1 if i not in list_2] == []
위 코드에서 list_1과 list_2는 서로 동일한 리스트입니다. 두 리스트에 포함된 각 딕셔너리가 같은 키와 값을 가지고 있기 때문입니다. 딕셔너리 내부에서 키-값 쌍이 나열되는 순서는 비교 결과에 아무런 영향을 주지 않습니다.
리스트 컴프리헨션을 사용하면 list_1에는 있지만 list_2에는 없는 항목을 손쉽게 걸러낼 수 있으며, 그 결과가 빈 리스트라면 두 리스트가 동일하다는 의미입니다.
두 딕셔너리 리스트 비교 후 차이점 출력하기
단순히 같은지 여부만 확인하는 것이 아니라, 어떤 딕셔너리 항목이 서로 다른지 직접 출력할 수도 있습니다.
예를 들어 다음과 같습니다.
if __name__ == '__main__':
list_1 = [
{'id': '123-abc', 'name': 'Mike', 'age': 40},
{'id': '123-efg', 'name': 'John', 'age': 24},
{'id': '123-xyz', 'name': 'Aly', 'age': 35}
]
list_2 = [
{'id': '123-abc', 'name': 'Mike', 'age': 40},
{'id': '123-efg', 'name': 'Jon', 'age': 24},
{'id': '123-xyz', 'name': 'Aly', 'age': 32}
]
for i in list_1:
if i not in list_2:
print(i)
실행 결과:
{'id': '123-efg', 'name': 'John', 'age': 24}
{'id': '123-xyz', 'name': 'Aly', 'age': 35}
위 예제에서는 이름('John' vs 'Jon')과 나이(35 vs 32)가 달라서 두 번째, 세 번째 딕셔너리가 차이 항목으로 출력되었습니다. 첫 번째 딕셔너리는 모든 키와 값이 일치하므로 출력되지 않습니다.
함수로 만들어 재사용하기
앞서 살펴본 로직을 함수로 정리하면 다음과 같이 작성할 수 있습니다. 두 리스트를 하나로 합친 뒤, 어느 한쪽에만 존재하는 항목을 찾아내는 방식입니다.
def compare_two_lists(list1: list, list2: list) -> bool:
"""
Compare two lists and logs the difference.
:param list1: first list.
:param list2: second list.
:return: if there is difference between both lists.
"""
diff = [i for i in list1 + list2 if i not in list1 or i not in list2]
result = len(diff) == 0
if not result:
print(f'There are {len(diff)} differences:\n{diff[:5]}')
return result
이 함수는 두 리스트 간에 차이가 없으면 True를 반환하고, 차이가 있으면 False를 반환하면서 차이 항목의 개수와 최대 5개의 샘플을 함께 출력해 줍니다.
Pandas DataFrame을 이용한 비교
데이터 양이 많거나 보다 체계적인 분석이 필요하다면 Pandas DataFrame을 활용하는 방법도 유용합니다. 아래 예제는 두 리스트를 DataFrame으로 변환한 뒤, outer merge와 _merge 지시자(indicator)를 사용해 차이가 있는 행만 추출하는 방식입니다.
from pandas import DataFrame
import pandas as pd
def compare_two_lists(list1: list, list2: list) -> bool:
"""
Compare two lists and logs the difference.
:param list1: first list.
:param list2: second list.
:return: if there is difference between both lists.
"""
df1 = pd.DataFrame(list1)
df2 = pd.DataFrame(list2)
diff = dataframe_difference(df1, df2)
result = len(diff) == 0
if not result:
print(f'There are {len(diff)} differences:\n{diff.head()}')
return result
def dataframe_difference(df1: DataFrame, df2: DataFrame) -> DataFrame:
"""
Find rows which are different between two DataFrames.
:param df1: first dataframe.
:param df2: second dataframe.
:return: if there is different between both dataframes.
"""
comparison_df = df1.merge(df2, indicator=True, how='outer')
diff_df = comparison_df[comparison_df['_merge'] != 'both']
return diff_df
이 방식은 _merge 열 값이 'both'가 아닌 행, 즉 어느 한쪽 DataFrame에만 존재하는 행들을 모두 찾아주기 때문에, 대량의 데이터에서 차이점을 빠르게 파악하는 데 특히 효과적입니다.
마무리
정리하면, Python에서 두 딕셔너리 리스트를 비교하는 대표적인 방법은 다음과 같습니다.
- 리스트 컴프리헨션 +
in연산자: 간단한 경우에 적합하며, 포함 여부만으로 동등성을 판단합니다. - 차이 항목 출력: 반복문이나 컴프리헨션으로 어느 항목이 다른지 구체적으로 확인할 수 있습니다.
- Pandas DataFrame 활용: 데이터가 많거나 행 단위 비교가 필요할 때 성능과 가독성 면에서 유리합니다.
상황에 맞는 방법을 선택하면 딕셔너리 리스트 간의 데이터 검증과 디버깅을 훨씬 쉽게 처리할 수 있습니다.