2017-12-20 4 views
2

파이썬 3.6에서 두 개의 사전 목록을 정렬하고 비교하는 방법을 찾으려고합니다. 나는 궁극적으로 list_dict_alist_dict_b==과 비교하고 True으로 평가하고 싶습니다. 여기Dicts Python 목록 정렬 및 비교

처럼 데이터가 모습입니다 :

list_dict_a = [ 
{'expiration_date': None, 'identifier_country': None, 'identifier_number': 'Male', 'identifier_type': 'Gender', 'issue_date': None}, 
{'expiration_date': None, 'identifier_country': 'VE', 'identifier_number': '1234567', 'identifier_type': 'Foo No.', 'issue_date': None}] 

list_dict_b = [ 
{'identifier_country': 'VE', 'expiration_date': None, 'identifier_type': 'Foo No.', 'issue_date': None, 'identifier_number': '1234567'}, 
{'identifier_country': None, 'expiration_date': None, 'identifier_type': 'Gender', 'issue_date': None, 'identifier_number': 'Male'}] 

데이터는 동일하지만 서로 다른 주문 (필자는 초기 주문에 대한 제어를 필요 없다)에 제공됩니다. print("does this match anything",list_dict_a == list_dict_b)

이도 가능 할 수 있습니다 : 다음과 같은 일을 할 때

나는 그런 그들을 비교하려고

, 나는 거짓 값을 얻을?

+0

https://stackoverflow.com/questions/9845369/comparing-2-lists-consisting-of-dictionaries-with-unique-keys-in-python –

답변

2

당신은 그들을 비교하기 전에 두 목록을 정렬하고 정렬 된 결과를 비교할 수 있습니다

>>> list_dict_a = [ 
     {'expiration_date': None, 'identifier_country': None, 'identifier_number': 'Male', 'identifier_type': 'Gender', 'issue_date': None}, 
     {'expiration_date': None, 'identifier_country': 'VE', 'identifier_number': '1234567', 'identifier_type': 'Foo No.', 'issue_date': None}] 

>>> list_dict_b = [ 
     {'identifier_country': 'VE', 'expiration_date': None, 'identifier_type': 'Foo No.', 'issue_date': None, 'identifier_number': '1234567'}, 
     {'identifier_country': None, 'expiration_date': None, 'identifier_type': 'Gender', 'issue_date': None, 'identifier_number': 'Male'}] 

>>> list_dict_a == list_dict_b 
False 
>>> def key_func(d): 
     items = ((k, v if v is not None else '') for k, v in d.items()) 
     return sorted(items) 
>>> sorted(list_dict_a, key=key_func) == sorted(list_dict_b, key=key_func) 
True 

다음 문제가되지 않습니다 각 목록 내에서 dicts의 순서.

dicts는 주문할 수 없으므로 key 함수를 전달해야합니다. 따라서 dict 객체를 비교할 때 각 dict 객체 쌍에 사용할 키를 정렬 함수에 알려야합니다. 각 사전에 대한 키는 단순히 (키, 값) 쌍의 정렬 된 목록입니다.

>>> dict_a0 = list_dict_a[0] 
>>> key_func(dict_a0) 
[('expiration_date', ''), ('identifier_country', ''), ('identifier_number', 'Male'), ('identifier_type', 'Gender'), ('issue_date', '')] 

각주

을 위해 (키, 값) 쌍리스트 기타 dicts '목록과 비교 가능하도록 다음과 같이

키 기능은 각 딕셔너리에 대한 키를 계산 , None 값을 빈 문자열로 변환해야했습니다. 이렇게하면 None 값을 다른 non-None 값과 비교할 수 있습니다.

위의 솔루션에서 기본 가정은 케이스의 모든 사전 값이 문자열 또는 None이고 "빈 값"이 (빈 문자열이 아닌) None으로 일관되게 표시된다는 것입니다. 그렇지 않은 경우 데이터에서 예상되는 임의의 dict 값에 대해 결과 목록이 항상 서로 비교되도록 보장하기 위해 key_func()을 적절하게 조정해야합니다.

또한 큰 dict의 경우 키 쌍 비교가 너무 느리기 때문에이 키 기능은 이상적이지 않을 수 있습니다. 따라서 각 dict에 대해 고유 한 해시 값을 계산하는 것이 더 좋습니다 (그러나 동등 함을 비교하는 dict의 경우 동일한 해시).list_dict_a의 각 딕셔너리가 list_dict_b에있는 경우

+0

만약'foo1 = sorted (list_dict_a)'와' foo2 = sorted (list_dict_b)'와 비교하려고합니다.'TypeError : unorderable types : dict()

+0

아 ... 죄송합니다. 파이썬 3은 놓쳤습니다. 답변을 조정할 것입니다. – plamut

+0

그리고 핵심 기능의 버그를 수정하십시오 :) – plamut

0

당신은 또한 확인할 수 있습니다

all([dict_a in list_dict_b for dict_a in list_dict_a]) 

Out[218]: True 
+1

이것은 O (n^2) 솔루션 ... 또는 O (a * b)입니다. 여기서 a와 b는 각각리스트 a와 b의 길이입니다. 그 차이는 더 큰 데이터 세트에 대해 상당 할 수 있습니다. – plamut

0

이 작업을 시도 할 수 있습니다 :

list_dict_a = [ 
{'expiration_date': None, 'identifier_country': None, 'identifier_number': 'Male', 'identifier_type': 'Gender', 'issue_date': None}, 
{'expiration_date': None, 'identifier_country': 'VE', 'identifier_number': '1234567', 'identifier_type': 'Foo No.', 'issue_date': None}] 

list_dict_b = [ 
{'identifier_country': 'VE', 'expiration_date': None, 'identifier_type': 'Foo No.', 'issue_date': None, 'identifier_number': '1234567'}, 
{'identifier_country': None, 'expiration_date': None, 'identifier_type': 'Gender', 'issue_date': None, 'identifier_number': 'Male'}] 
new_list = sorted(list_dict_a, key=lambda x:x['identifier_country'] is not None, reverse=True) 
print(new_list == list_dict_b) 

출력 :

True 

당신이 알고하지 않으면 열쇠는 원래 다음과 같이 시도 할 수 있습니다.

new_list = sorted(list_dict_a, key=lambda x:x.get('identifier_country', None) is not None, reverse=True) 
+0

키를 모르는 경우 대신'key = lambda x : x [0]'을 할 수 있습니까? –

+0

@unseen_damage no, 람다 함수의 범위에서'x'는 사전이고,'x [0]'는'KeyError'를 발생시킵니다. 그러나'dict.get'을 사용하고 기본 세그먼트를 제공 할 수 있습니다. 최근 편집을 참조하십시오. – Ajax1234