[python] Python-고유 한 사전 목록

사전 목록이 있다고 가정 해 보겠습니다.

[
    {'id': 1, 'name': 'john', 'age': 34},
    {'id': 1, 'name': 'john', 'age': 34},
    {'id': 2, 'name': 'hanna', 'age': 30},
]

고유 한 사전 목록을 가져와야합니다 (중복 제거).

[
    {'id': 1, 'name': 'john', 'age': 34},
    {'id': 2, 'name': 'hanna', 'age': 30},
]

파이썬에서 이것을 달성하는 가장 효율적인 방법으로 나를 도울 수 있습니까?



답변

따라서 키가있는 임시 dict을 만드십시오 id. 중복 항목을 필터링합니다. values()DICT의 목록이 될 것입니다

Python2.7에서

>>> L=[
... {'id':1,'name':'john', 'age':34},
... {'id':1,'name':'john', 'age':34},
... {'id':2,'name':'hanna', 'age':30},
... ]
>>> {v['id']:v for v in L}.values()
[{'age': 34, 'id': 1, 'name': 'john'}, {'age': 30, 'id': 2, 'name': 'hanna'}]

Python3에서

>>> L=[
... {'id':1,'name':'john', 'age':34},
... {'id':1,'name':'john', 'age':34},
... {'id':2,'name':'hanna', 'age':30},
... ]
>>> list({v['id']:v for v in L}.values())
[{'age': 34, 'id': 1, 'name': 'john'}, {'age': 30, 'id': 2, 'name': 'hanna'}]

Python2.5 / 2.6에서

>>> L=[
... {'id':1,'name':'john', 'age':34},
... {'id':1,'name':'john', 'age':34},
... {'id':2,'name':'hanna', 'age':30},
... ]
>>> dict((v['id'],v) for v in L).values()
[{'age': 34, 'id': 1, 'name': 'john'}, {'age': 30, 'id': 2, 'name': 'hanna'}]


답변

집합에서 공통 요소를 찾는 일반적인 방법은 Python의 set클래스 를 사용하는 것 입니다. 모든 요소를 ​​세트에 추가 한 다음 세트를로 변환 list하고 복제본은 사라집니다.

물론 문제 set()는에 해시 가능 항목 만 포함 할 수 있고 해시 가능 dict하지 않다는 것입니다.

이 문제가 발생하면 해결책은 각각 dict을 나타내는 문자열 로 변환 dict한 다음 모든 문자열을 추가 한 set()다음 문자열 값 을 a 로 읽고 list()다시 변환하는 것 dict입니다.

dict문자열 형식 의 올바른 표현 은 JSON 형식입니다. 그리고 파이썬에는 JSON을위한 내장 모듈이 있습니다 ( json물론 호출됩니다 ).

나머지 문제는의 요소 dict가 정렬되지 않았으며 Python dict이를 JSON 문자열 로 변환 할 때 동등한 사전을 나타내지 만 동일한 문자열이 아닌 두 개의 JSON 문자열을 얻을 수 있다는 것입니다. 쉬운 해결책은 sort_keys=True호출 할 때 인수를 전달하는 것 json.dumps()입니다.

편집 :이 솔루션은 주어진 dict부분이 다를 수 있다고 가정했습니다 . dict같은 "id"값을 가진 모든 사람 이 같은 값을 dict가진 다른 모든 사람 과 일치 한다고 가정 할 수 있다면 "id"이것은 과잉입니다. @gnibbler의 솔루션은 더 빠르고 쉽습니다.

편집 : 이제 André Lima의 ID가 중복 된 경우 전체 dict가 중복 이라고 가정하는 것이 안전하다는 의견이 있습니다 . 따라서이 답변은 과잉이며 @gnibbler의 답변을 권장합니다.


답변

사전이 모든 항목으로 고유하게 식별되는 경우 (ID를 사용할 수 없음) JSON을 사용하여 답변을 사용할 수 있습니다. 다음은 JSON을 사용하지 않는 모든 대안이며 모든 사전 값이 변경되지 않는 한 작동합니다.

[dict(s) for s in set(frozenset(d.items()) for d in L)]


답변

numpy 라이브러리를 사용할 수 있습니다 (Python2.x에서만 작동).

   import numpy as np

   list_of_unique_dicts=list(np.unique(np.array(list_of_dicts)))

Python 3.x (및 최신 버전의 numpy)와 함께 작동하려면 dicts 배열을 numpy 문자열 배열로 변환해야합니다.

list_of_unique_dicts=list(np.unique(np.array(list_of_dicts).astype(str)))


답변

다음은 상당히 효율적이지 않은 것으로 생각되지만 합리적인 솔루션은 다음과 같습니다.

>>> ds = [{'id':1,'name':'john', 'age':34},
...       {'id':1,'name':'john', 'age':34},
...       {'id':2,'name':'hanna', 'age':30}
...       ]
>>> map(dict, set(tuple(sorted(d.items())) for d in ds))
[{'age': 30, 'id': 2, 'name': 'hanna'}, {'age': 34, 'id': 1, 'name': 'john'}]


답변

이 때문에 id중복을 검출하기위한 충분하고,이 id해쉬 인 다음을 가지고 사전을 통해 실행 ‘안에 id키로. 각 키의 값은 원래 사전입니다.

deduped_dicts = dict((item["id"], item) for item in list_of_dicts).values()

Python 3에서는 values()목록을 반환하지 않습니다. 해당 표현의 오른쪽 전체를로 감싸 야하며 표현 list()의 고기를 독창적으로 이해하여보다 경제적으로 작성할 수 있습니다.

deduped_dicts = list({item["id"]: item for item in list_of_dicts}.values())

결과는 원본과 동일한 순서가 아닐 수 있습니다. 이것이 요구 사항이라면을 Collections.OrderedDict대신 사용할 수 있습니다 dict.

따로, as 키를 사용하는 사전에 데이터를 보관 하는 것이 좋습니다 id.


답변

a = [
{'id':1,'name':'john', 'age':34},
{'id':1,'name':'john', 'age':34},
{'id':2,'name':'hanna', 'age':30},
]

b = {x['id']:x for x in a}.values()

print(b)

출력 :

[{ ‘age’: 34, ‘id’: 1, ‘name’: ‘john’}, { ‘age’: 30, ‘id’: 2, ‘name’: ‘hanna’}]