[python] 목록에서 중복 제거
목록에 중복 항목이 있는지 확인하고 중복 여부를 확인하고 복제 / 제거되지 않은 항목이 포함 된 새 목록을 반환하는 프로그램을 작성해야합니다. 이것이 내가 가진 것이지만 정직하게 무엇을 해야할지 모르겠습니다.
def remove_duplicates():
t = ['a', 'b', 'c', 'd']
t2 = ['a', 'c', 'd']
for t in t2:
t.append(t.remove())
return t
답변
고유 한 항목 모음을 얻는 일반적인 방법은을 사용하는 것 set
입니다. 세트는 고유 한 개체 의 순서 가 없는 모음입니다 . iterable에서 세트를 만들려면 간단히 내장 함수에 전달하면됩니다 . 나중에 실제 목록을 다시 필요로하는 경우에도 마찬가지로 세트를 함수에 전달할 수 있습니다 .set()
list()
다음 예제는 수행하려는 모든 것을 다루어야합니다.
>>> t = [1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> t
[1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> list(set(t))
[1, 2, 3, 5, 6, 7, 8]
>>> s = [1, 2, 3]
>>> list(set(t) - set(s))
[8, 5, 6, 7]
예제 결과에서 볼 수 있듯이 원래 순서는 유지되지 않습니다 . 위에서 언급했듯이 세트 자체는 정렬되지 않은 컬렉션이므로 순서가 손실됩니다. 세트를 목록으로 다시 변환하면 임의의 순서가 작성됩니다.
질서 유지
순서가 중요하다면 다른 메커니즘을 사용해야합니다. 이를위한 가장 일반적인 해결책은 OrderedDict
삽입 중에 키 순서를 유지하는 것입니다.
>>> from collections import OrderedDict
>>> list(OrderedDict.fromkeys(t))
[1, 2, 3, 5, 6, 7, 8]
Python 3.7부터 내장 사전은 삽입 순서를 유지하도록 보장되므로 Python 3.7 이상 (또는 CPython 3.6)을 사용하는 경우 직접 사용할 수도 있습니다.
>>> list(dict.fromkeys(t))
[1, 2, 3, 5, 6, 7, 8]
사전을 먼저 작성한 다음 목록을 작성하는 데 약간의 오버 헤드가있을 수 있습니다. 실제로 주문을 보존 할 필요가없는 경우, 특히 더 많은 작업을 수행 할 수 있기 때문에 세트를 사용하는 것이 좋습니다. 중복을 제거 할 때 순서를 유지하는 자세한 방법과 다른 방법은 이 질문 을 확인하십시오 .
마지막으로 / 솔루션 set
과 OrderedDict
/ dict
솔루션 모두 아이템을 해시 할 수 있어야 합니다. 이것은 보통 불변이어야 함을 의미합니다. 해시 가능하지 않은 항목 (예 : 목록 개체)을 처리해야하는 경우 기본적으로 중첩 된 루프의 모든 다른 항목과 모든 항목을 비교해야하는 느린 접근 방식을 사용해야합니다.
답변
Python 2.7 에서 원래 순서대로 유지하면서 iterable에서 중복을 제거하는 새로운 방법은 다음과 같습니다.
>>> from collections import OrderedDict
>>> list(OrderedDict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']
Python 3.5 에서 OrderedDict에는 C 구현이 있습니다. 내 타이밍에 따르면 이것이 현재 Python 3.5에 대한 다양한 접근 방식 중 가장 빠르고 가장 짧습니다.
Python 3.6 에서는 일반 dict이 순서가 작고 간결 해졌습니다. (이 기능은 CPython 및 PyPy 용이지만 다른 구현에는 없을 수 있습니다). 이를 통해 주문을 유지하면서 새로운 가장 빠른 중복 제거 방법을 얻을 수 있습니다.
>>> list(dict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']
Python 3.7 에서는 일반 구현이 모든 구현에서 순서대로 보장됩니다. 가장 짧고 빠른 솔루션은 다음과 같습니다.
>>> list(dict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']
답변
그것은 하나의 라이너입니다 : list(set(source_list))
트릭을 할 것입니다.
A set
는 중복 될 수없는 것입니다.
업데이트 : 주문 보존 접근 방식은 두 줄입니다.
from collections import OrderedDict
OrderedDict((x, True) for x in source_list).keys()
여기서 우리 OrderedDict
는 키의 삽입 순서 를 기억하고 특정 키의 값이 업데이트 될 때 키를 변경하지 않는다는 사실을 사용합니다 . 우리 True
는 값으로 삽입 하지만 아무것도 삽입 할 수 없으며 값은 사용되지 않습니다. ( 무시 된 값을 가진 set
것과 비슷하게 작동합니다 dict
.)
답변
>>> t = [1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> t
[1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> s = []
>>> for i in t:
if i not in s:
s.append(i)
>>> s
[1, 2, 3, 5, 6, 7, 8]
답변
주문에 신경 쓰지 않으면 다음과 같이하십시오.
def remove_duplicates(l):
return list(set(l))
A set
는 중복되지 않아야합니다.
답변
중복의 첫 번째 요소의 순서를 유지하면서 새 목록을 만들려면 L
newlist=[ii for n,ii in enumerate(L) if ii not in L[:n]]
예를 들어 if L=[1, 2, 2, 3, 4, 2, 4, 3, 5]
다음 newlist
될 것입니다[1,2,3,4,5]
이것은 추가하기 전에 각각의 새로운 요소가 목록에 이전에 나타나지 않았는지 확인합니다. 또한 수입이 필요하지 않습니다.
답변
동료가 오늘 코드 검토를 위해 자신의 코드의 일부로 허용 된 답변을 보냈습니다. 해당 답변의 우아함을 확실히 존경하지만 공연에 만족하지 않습니다. 이 솔루션을 사용해 보았습니다 ( 검색 시간을 줄이기 위해 설정 사용 )
def ordered_set(in_list):
out_list = []
added = set()
for val in in_list:
if not val in added:
out_list.append(val)
added.add(val)
return out_list
효율성을 비교하기 위해 100 개의 정수로 구성된 임의 샘플을 사용했습니다. 62는 고유했습니다.
from random import randint
x = [randint(0,100) for _ in xrange(100)]
In [131]: len(set(x))
Out[131]: 62
다음은 측정 결과입니다
In [129]: %timeit list(OrderedDict.fromkeys(x))
10000 loops, best of 3: 86.4 us per loop
In [130]: %timeit ordered_set(x)
100000 loops, best of 3: 15.1 us per loop
솔루션에서 세트를 제거하면 어떻게됩니까?
def ordered_set(inlist):
out_list = []
for val in inlist:
if not val in out_list:
out_list.append(val)
return out_list
결과는 OrderedDict 만큼 나쁘지는 않지만 원래 솔루션의 3 배 이상입니다.
In [136]: %timeit ordered_set(x)
10000 loops, best of 3: 52.6 us per loop