source

주문을 유지하면서 목록에서 중복 항목을 제거하려면 어떻게 해야 합니까?

gigabyte 2022. 9. 6. 22:21
반응형

주문을 유지하면서 목록에서 중복 항목을 제거하려면 어떻게 해야 합니까?

주문을 유지하면서 목록에서 중복 항목을 제거하려면 어떻게 해야 합니까?세트를 사용하여 중복을 제거하면 원래 주문이 삭제됩니다.붙박이 사자성어나 피토닉 사자성어가 있나요?

관련 질문:Python에서 순서를 유지하면서 모든 요소가 고유하도록 목록에서 중복을 제거하는 가장 빠른 알고리즘은 무엇입니까?

여기 몇 가지 대안이 있습니다.http://www.peterbe.com/plog/uniqifiers-benchmark

가장 빠른 것:

def f7(seq):
    seen = set()
    seen_add = seen.add
    return [x for x in seq if not (x in seen or seen_add(x))]

「」를 할당하는 seen.add로로 합니다.seen_add '만'이라고 부르는 것이 '만'이라고 부르면 안 돼요.seen.add이며, Python입니다seen.add각 반복은 로컬 변수를 해결하는 것보다 비용이 많이 듭니다. seen.add반복 간에 변경될 수 있으며 실행 시간이 충분히 스마트하지 않아 이를 배제할 수 없습니다.안전하게 플레이하려면 매번 물체를 확인해야 합니다.

같은 데이터 세트에서 이 기능을 많이 사용할 계획이라면 http://code.activestate.com/recipes/528878/를 주문하는 것이 좋습니다.

작업별 O(1) 삽입, 삭제 및 멤버 체크.

추가 메모: (소량 추가 메모seen.add() 반환하다None따라서 위의 내용은 세트업데이트를 시행하는 방법으로서만 사용할 수 있으며 논리 테스트의 일부로서는 사용할 수 없습니다).

최적의 솔루션은 Python 버전 및 환경 제약에 따라 달라집니다.

Python 3.7+(및 구현 세부사항으로 3.6을 지원하는 대부분의 인터프리터):

.53.후.Python 2.5.0에서 Python 3.7에서 언어 보증이 이루어졌습니다.dict는 삽입 ( 3)보다 입니다.collections.OrderedDict따라서 가장 빠른 솔루션은 가장 간단한 솔루션이기도 합니다.

>>> items = [1, 2, 0, 1, 3, 2]
>>> list(dict.fromkeys(items))  # Or [*dict.fromkeys(items)] if you prefer
[1, 2, 0, 3]

맘에 들다list(set(items))에 의해, 모든 이 C 상)에 푸시 만, 「C」(CPython)이기 때문에,dict삽입순서입니다.dict.fromkeys순서를 잃지 않습니다.list(set(items))(일반적으로 50~100% 더 오래 걸리지만) 다른 주문 유지 솔루션보다 훨씬 빠릅니다(리스트콤에서 사용하는 해킹 시간의 약 절반).

중요사항:unique_everseen결 from의 more_itertools(아래 참조)는 게으름과 비사용 입력 항목에 대한 지원이라는 점에서 몇 가지 고유한 이점이 있습니다. 이러한 기능이 필요한 경우 이 솔루션만이 유효합니다.

Python 3.5(및 성능이 중요하지 않은 경우 모든 이전 버전)

Raymond가 지적했듯이 CPython 3.5에서는OrderedDict의 이해 C보다 .추측 리스트의 이해 해크는, 보다 느립니다.OrderedDict.fromkeys(마지막에 실제로 목록이 필요한 경우를 제외하고 입력이 매우 짧은 경우에만 해당).3.에 가장 은 CPython 3.5입니다.OrderedDict의 3.에 하는 양dict:

>>> from collections import OrderedDict
>>> items = [1, 2, 0, 1, 3, 2]
>>> list(OrderedDict.fromkeys(items))
[1, 2, 0, 3]

CPython 3.4 이전 버전에서는 다른 솔루션보다 속도가 느리므로 프로파일링에서 더 나은 솔루션이 필요한 경우 계속 읽어보십시오.

Python 3.4 이전 버전(성능이 중요하고 타사 모듈을 사용할 수 있는 경우)

@abarnert가 말했듯이 라이브러리(pip install more_itertools에는, 이 문제를 판독할 수 없는 일 없이 해결할 수 있는 기능이 포함되어 있습니다( ).not seen.add)의 리스트 컴프리션의 돌연변이.이것이 가장 빠른 해결책이기도 합니다.

>>> from more_itertools import unique_everseen
>>> items = [1, 2, 0, 1, 3, 2]
>>> list(unique_everseen(items))
[1, 2, 0, 3]

간단한 라이브러리 Import만 하면 해킹은 없습니다.

모듈은 다음과 같은 반복 도구 레시피를 적용하고 있습니다.

def unique_everseen(iterable, key=None):
    "List unique elements, preserving order. Remember all elements ever seen."
    # unique_everseen('AAAABBBCCDAABBB') --> A B C D
    # unique_everseen('ABBCcAD', str.lower) --> A B C D
    seen = set()
    seen_add = seen.add
    if key is None:
        for element in filterfalse(seen.__contains__, iterable):
            seen_add(element)
            yield element
    else:
        for element in iterable:
            k = key(element)
            if k not in seen:
                seen_add(k)
                yield element

but하 the the the the the the the와는 itertools에서는, 「코스트」에 포함되는 의 경우는, 「Recipe」를 서포트하고 .iterable은 해석할 수 은 '알고리즘」이 됩니다.O(n²) . , . . . . . . . . . . .O(n)」를 참조해 주세요.

중요사항:여기 있는 다른 모든 솔루션과 달리unique_everseen느긋하게 할 수 사용량이 같아집니다).최대 메모리 사용량이 같아집니다(결국 기반이 되는 메모리 사용량이 같아집니다).set). 하지만 그렇지 않으면list결과를 반복하기만 하면 첫 번째 고유 항목을 처리하기 전에 입력 전체가 중복 제거될 때까지 기다리지 않고 발견된 고유 항목을 즉시 처리할 수 있습니다.

Python 3.4 이전 버전, 성능이 중요하고 타사 모듈을 사용할 수 없는 경우

두 가지 옵션이 있습니다.

  1. 레시피를 코드에 복사하여 붙여넣기하여more_itertools의 예

  2. 가 listcomp를 및할 수 합니다.set것을하다: 본 것을 추적하다.

    seen = set()
    [x for x in seq if x not in seen and not seen.add(x)]
    

    그 추악한 해킹에 의존하면서 말이죠.

     not seen.add(x)
    

    합니다.set.add in-place로 입니다.Nonenot NoneTrue.

위의 모든 솔루션은 다음과 같습니다.O(n) calling(콜 저장))unique_everseen할 수 , 즉, 「반복할 수 없는 아이템에 대해서」, 「반복할 수 없는 아이템 「」O(n²) 다른 것들은 즉시 실패한다.TypeError있을 때가 아닌 코드 경로)아서, 모든 해결책 충분히 성능 기준에 맞는 있다.어떤 사용할 언어를 당신은 spec/interpreter/third-party 모듈 의존할 수 있는 버전에 만약 나중에 이 코드를 유지하고 있는 사람이 살인적인 분위기에 끝나겠지, 이어지든 말든 성능은 중요한( 그렇다 하고 그것은 보통지 않는다고 가정하지 않아), 그리고 가장 중요한 것은 가독성(, 왜냐하면 당신의 영리한 micro-optimization 아마도 w. 달려 있로)의 가치도 없다.

CPython 3.6+(그리고 모든 다른 파이썬 구현 파이선 3.7+부터 시작하여)에서, 사전, 그래서 길이 원본 순서에 맞는 것이다하면iterable에서 중복을 제거하도록 강제된다.

>>> list(dict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']

파이선 3.5(파이선 2.7포함)고 아래에서, OrderedDict를 사용한다.내 타이밍은 이 지금 둘 다, Python3.5( 때;C구현했다 앞서 3.5미터에서 아직도 그 비젼에는 해결책 아니지만 가장 빠른)에 대한 다양한 접근법의 짧은 빠른 것을 보여 준다.

>>> from collections import OrderedDict
>>> list(OrderedDict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']

지만 여기 해결책은 꽤 빨리 많은 상황에서 죽어 사용하기가 간단하다는 것이다 pandas를 사용하고 있다 죽은 말( 좋은 답이 이 질문은 매우 벌써 오래 된 많은)을 차기도 한다.

import pandas as pd

my_list = [0, 1, 2, 3, 4, 1, 2, 3, 5]

>>> pd.Series(my_list).drop_duplicates().tolist()
# Output:
# [0, 1, 2, 3, 4, 5]

파이선 3.7, 위에서, 사전은 기본 삽입 위해 기억하는 것을 보장 받는다.이 질문에 대한 대답은 시국을 요약하였다.

OrderedDict해결책이 되어 어떤 수입 발언 없이 우리는 단순히 발행할 수 있습니다:구식이 된다.

>>> lst = [1, 2, 1, 3, 3, 2, 4]
>>> list(dict.fromkeys(lst))
[1, 2, 3, 4]
sequence = ['1', '2', '3', '3', '6', '4', '5', '6']
unique = []
[unique.append(item) for item in sequence if item not in unique]

→ 고유 →['1', '2', '3', '6', '4', '5']

from itertools import groupby
[ key for key,_ in groupby(sortedList)]

그 리스트는 정렬될, 필요 충분 조건은 평등 가치 함께 그룹화됩니다 필요가 없는다.

편집:나는"주문을 보존하기"은 리스트는 명령이다는 것을 암시하고 있었다.만약 이 있지 않다면, 그때는 MizardX에서 해결 방안은 맞네요.

지역 사회 편집:이것은 하지만 가장 우아한 방법"압축 파일을 단일 요소에 연속 요소 중복".

질서를 유지하고 싶다면

다음과 같이 시험해 볼 수 있습니다.

list1 = ['b','c','d','b','c','a','a']    
list2 = list(set(list1))    
list2.sort(key=list1.index)    
print list2

또는 다음과 같이 할 수 있습니다.

list1 = ['b','c','d','b','c','a','a']  
list2 = sorted(set(list1),key=list1.index)  
print list2 

다음 작업도 수행할 수 있습니다.

list1 = ['b','c','d','b','c','a','a']    
list2 = []    
for i in list1:    
    if not i in list2:  
        list2.append(i)`    
print list2

다음과 같이 쓸 수도 있습니다.

list1 = ['b','c','d','b','c','a','a']    
list2 = []    
[list2.append(i) for i in list1 if not i in list2]    
print list2 

외부1 모듈로부터 이러한 기능의 다른(매우 퍼포먼스) 실장을 추가하는 것만으로, 다음과 같습니다.

>>> from iteration_utilities import unique_everseen
>>> lst = [1,1,1,2,3,2,2,2,1,3,4]

>>> list(unique_everseen(lst))
[1, 2, 3, 4]

타이밍

가지 3.6. 3.6, 피톤 3.6 등입니다.OrderedDict.fromkeys,f7 ★★★★★★★★★★★★★★★★★」more_itertools.unique_everseen:

%matplotlib notebook

from iteration_utilities import unique_everseen
from collections import OrderedDict
from more_itertools import unique_everseen as mi_unique_everseen

def f7(seq):
    seen = set()
    seen_add = seen.add
    return [x for x in seq if not (x in seen or seen_add(x))]

def iteration_utilities_unique_everseen(seq):
    return list(unique_everseen(seq))

def more_itertools_unique_everseen(seq):
    return list(mi_unique_everseen(seq))

def odict(seq):
    return list(OrderedDict.fromkeys(seq))

from simple_benchmark import benchmark

b = benchmark([f7, iteration_utilities_unique_everseen, more_itertools_unique_everseen, odict],
              {2**i: list(range(2**i)) for i in range(1, 20)},
              'list size (no duplicates)')
b.plot()

여기에 이미지 설명 입력

또한 더 많은 중복을 사용하여 테스트도 실시하여 차이가 있는지 확인합니다.

import random

b = benchmark([f7, iteration_utilities_unique_everseen, more_itertools_unique_everseen, odict],
              {2**i: [random.randint(0, 2**(i-1)) for _ in range(2**i)] for i in range(1, 20)},
              'list size (lots of duplicates)')
b.plot()

여기에 이미지 설명 입력

또한 하나의 값만 포함하는 값:

b = benchmark([f7, iteration_utilities_unique_everseen, more_itertools_unique_everseen, odict],
              {2**i: [1]*(2**i) for i in range(1, 20)},
              'list size (only duplicates)')
b.plot()

여기에 이미지 설명 입력

, 「」는iteration_utilities.unique_everseen이데올로기 때문에


★★★★★★★★★★★★★★★★★.iteration_utilities.unique_everseen을 처리할 도 있습니다(, 「」는 「」로 설정되어 있습니다).O(n*n)(Performance)가 아닌O(n)퍼포먼스를 향상시킵니다).

>>> lst = [{1}, {1}, {2}, {1}, {3}]

>>> list(unique_everseen(lst))
[{1}, {2}, {3}]

1 면책사항:저는 그 패키지의 작성자입니다.

또 다른 매우 오래된 질문에 대한 매우 늦은 답변:

레시피에는 이 기능을 하는 기능이 있습니다.seen technology, 설정 방법:

  • 합니다.key★★★★★★ 。
  • 꼴사나운 해커를 쓰지 않는다.
  • 합니다.seen.addf7이 동작도 합니다만, 일부의 버전에서는 동작하지 않습니다).
  • 하여 루프를 합니다.ifilterfalsePython의 Python의 한 요소 Python의 모든 에 대해 됩니다.)ifilterfalse물론입니다만, 이것은 C단위로, 훨씬 더 빠릅니다.)

실제로 이 속도보다 빠릅니까?f7데이터에 따라 다르므로 테스트하고 확인해야 합니다.는, 「」를 참조해 주세요.f7는 listcomp를 (직접 listcomp를 할 수 .)appendyield 또는를 ing으로 수 .listlistcomp하다 LIST_APPEND입니다.어쨌든 보통 몇 마이크로초를 짜내는 것은 쉽게 이해할 수 있고 재사용 가능하며 이미 작성된 기능을 사용하는 것만큼 중요하지 않습니다. 이 기능은 꾸미고 싶을 때 DSU를 필요로 하지 않습니다.

모든 레시피와 마찬가지로 에서도 사용할 수 있습니다.

이 no-no-no-no-no-no-no-no-no-no-no-nkey을 사용하다

def unique(iterable):
    seen = set()
    seen_add = seen.add
    for element in itertools.ifilterfalse(seen.__contains__, iterable):
        seen_add(element)
        yield element

MizardX에 따라 해시 가능한 유형(예: 목록)이 없는 경우:

def f7_noHash(seq)
    seen = set()
    return [ x for x in seq if str( x ) not in seen and not seen.add( str( x ) )]

5배 빠른 속도, 변종 감소 및 고급화

>>> l = [5, 6, 6, 1, 1, 2, 2, 3, 4]
>>> reduce(lambda r, v: v in r[1] and r or (r[0].append(v) or r[1].add(v)) or r, l, ([], set()))[0]
[5, 6, 1, 2, 3, 4]

설명:

default = (list(), set())
# use list to keep order
# use set to make lookup faster

def reducer(result, item):
    if item not in result[1]:
        result[0].append(item)
        result[1].add(item)
    return result

>>> reduce(reducer, l, default)[0]
[5, 6, 1, 2, 3, 4]

간단한 방법은 다음과 같습니다.

list1 = ["hello", " ", "w", "o", "r", "l", "d"]
sorted(set(list1 ), key=list1.index)

다음과 같은 출력을 나타냅니다.

["hello", " ", "w", "o", "r", "l", "d"]

팬더 사용자들은 확인해야 한다.

>>> import pandas as pd
>>> lst = [1, 2, 1, 3, 3, 2, 4]
>>> pd.unique(lst)
array([1, 2, 3, 4])

함수는 NumPy 어레이를 반환합니다.필요한 경우 메서드를 사용하여 목록으로 변환할 수 있습니다.

의 Haskell을하는 데 nub목록에 대한 함수, 이것은 재귀적 접근법입니다.

def unique(lst):
    return [] if lst==[] else [lst[0]] + unique(filter(lambda x: x!= lst[0], lst[1:]))

예:

In [118]: unique([1,5,1,1,4,3,4])
Out[118]: [1, 5, 4, 3]

데이터 크기를 늘리기 위해 시도해보니 선형 이하의 시간 복잡성이 확인되었습니다(확정적이지는 않지만 일반 데이터라면 충분하다는 것을 시사함).

In [122]: %timeit unique(np.random.randint(5, size=(1)))
10000 loops, best of 3: 25.3 us per loop

In [123]: %timeit unique(np.random.randint(5, size=(10)))
10000 loops, best of 3: 42.9 us per loop

In [124]: %timeit unique(np.random.randint(5, size=(100)))
10000 loops, best of 3: 132 us per loop

In [125]: %timeit unique(np.random.randint(5, size=(1000)))
1000 loops, best of 3: 1.05 ms per loop

In [126]: %timeit unique(np.random.randint(5, size=(10000)))
100 loops, best of 3: 11 ms per loop

또, 다른 업무에 의해서도, 개성이 용이하게 일반화할 수 있는 것도 흥미롭다고 생각합니다.다음과 같이 합니다.

import operator
def unique(lst, cmp_op=operator.ne):
    return [] if lst==[] else [lst[0]] + unique(filter(lambda x: cmp_op(x, lst[0]), lst[1:]), cmp_op)

예를 들어 고유성을 위해 동일한 정수로 반올림하는 개념을 사용하는 함수를 다음과 같이 전달할 수 있습니다.

def test_round(x,y):
    return round(x) != round(y)

그러면 unique(some_list, test_round)는 목록의 고유한 요소를 제공합니다. 여기서 유니크성은 더 이상 전통적인 평등을 의미하지 않고(이 문제에 대한 모든 종류의 세트 기반 또는 딕트 키 기반 접근방식을 사용함으로써 암시됨), 대신 요소가 발생할 수 있는 각 정수 K에 대해 K로 반올림되는 첫 번째 요소만 취하도록 의도됩니다.d to. 예:

In [6]: unique([1.2, 5, 1.9, 1.1, 4.2, 3, 4.8], test_round)
Out[6]: [1.2, 5, 1.9, 4.2, 3]

목록 이해는 기호 '_[1]'로 작성되므로 참조할 수 있습니다.
예를 들어, 다음 함수는 목록 이해를 참조하여 요소의 순서를 변경하지 않고 요소의 목록을 고유하게 표시합니다.

def unique(my_list): 
    return [x for x in my_list if x not in locals()['_[1]']]

데모:

l1 = [1, 2, 3, 4, 1, 2, 3, 4, 5]
l2 = [x for x in l1 if x not in locals()['_[1]']]
print l2

출력:

[1, 2, 3, 4, 5]

이 문제 . 이 솔루션들은 문제 없습니다.
주문을 보존하면서 중복을 제거하기 위해 이 페이지의 다른 부분에 제시된 뛰어난 솔루션이 있습니다.

seen = set()
[x for x in seq if not (x in seen or seen.add(x))]

및 변동. 예:

seen = set()
[x for x in seq if x not in seen and not seen.add(x)]

는 단순하고 최소적이며 최적의 효율을 위해 올바른 해시를 도입하기 때문에 매우 인기가 있습니다. 큰 하는 것 .None인 'seen.add(x)논리적 표현에서 상수(따라서 초과/초과) 값은 단지 그 부작용 때문에 진부하거나 혼란스럽기 때문이다.

2. 1회 됩니다.2 . ... , 、 1 복 、 1 복 、 1 회 、 1 회 회 회 회회 。
놀랍게도, 이 주제에 대한 토론과 토론의 양을 고려할 때, 실제로 간과된 것처럼 보이는 코드에는 상당한 개선이 있습니다.그림과 같이 각 "테스트 앤 세트" 반복에는 2개의 해시 룩업이 필요합니다.멤버십을 테스트하는 첫 번째 해시 룩업x not in seen seen.add(x)첫 번째 조작은 두 번째 조작이 항상 성공한다는 것을 보증하기 때문에, 여기에는 불필요한 중복 작업이 있습니다.또한 전체적인 기법이 매우 효율적이기 때문에 과도한 해시 검색은 남은 작업 중 가장 비용이 많이 드는 부분이 될 수 있습니다.

3 신,, the, the,set★★★★★★★★★★★★★★★★★★!
에서는, 「 」만을 호출하고 에 주의해 주세요.set.add그렇게 하면 항상 세트 멤버십이 증가한다는 것을 알고 있습니다.set자체는 복제를 거부할 기회가 없습니다.우리의 코드 스니펫은 본질적으로 그 역할을 스스로 침해하고 있습니다.명시적인 2단계 테스트 앤 세트 코드를 사용하는 것은 강도입니다.set그 복제품 자체를 배제할 수 있는 핵심 능력을 가지고 있습니다.

코드 4. 「 」 、 「 」
다음 버전에서는 반복당 해시 룩업 횟수가 2회에서 1회로 절반으로 줄어듭니다.

seen = set()
[x for x in seq if len(seen) < len(seen.add(x) or seen)]

라이너가 1개 필요한 경우는, 다음과 같은 것이 도움이 됩니다.

reduce(lambda x, y: x + y if y[0] not in x else x, map(lambda x: [x],lst))

...은 효과가 있지만 내가 틀렸다면 정정해야 한다.

MizardX의 답변은 다양한 접근 방식을 제공합니다.

내가 큰 소리로 생각하면서 생각해낸 것은 다음과 같다.

mylist = [x for i,x in enumerate(mylist) if x not in mylist[i+1:]]

일종의 추악한 목록 이해 해킹을 할 수도 있어요

[l[i] for i in range(len(l)) if l.index(l[i]) == i]

with with with with with with with with with with with with with로 비교적 효과적인 _sorted_ a numpy★★★★★★★★★★★★★★★★★★:

b = np.array([1,3,3, 8, 12, 12,12])    
numpy.hstack([b[0], [x[0] for x in zip(b[1:], b[:-1]) if x[0]!=x[1]]])

출력:

array([ 1,  3,  8, 12])
l = [1,2,2,3,3,...]
n = []
n.extend(ele for ele in l if ele not in set(n))

세트의 O(1) 검색을 사용하여 요소를 새 목록에 포함할지 여부를 결정하는 제너레이터 식입니다.

단순한 재귀적 솔루션:

def uniquefy_list(a):
    return uniquefy_list(a[1:]) if a[0] in a[1:] else [a[0]]+uniquefy_list(a[1:]) if len(a)>1 else [a[0]]

시퀀스에서 중복된 값을 제거하지만 나머지 항목의 순서는 유지합니다.범용 제너레이터 기능 사용.

# for hashable sequence
def remove_duplicates(items):
    seen = set()
    for item in items:
        if item not in seen:
            yield item
            seen.add(item)

a = [1, 5, 2, 1, 9, 1, 5, 10]
list(remove_duplicates(a))
# [1, 5, 2, 9, 10]



# for unhashable sequence
def remove_duplicates(items, key=None):
    seen = set()
    for item in items:
        val = item if key is None else key(item)
        if val not in seen:
            yield item
            seen.add(val)

a = [ {'x': 1, 'y': 2}, {'x': 1, 'y': 3}, {'x': 1, 'y': 2}, {'x': 2, 'y': 4}]
list(remove_duplicates(a, key=lambda d: (d['x'],d['y'])))
# [{'x': 1, 'y': 2}, {'x': 1, 'y': 3}, {'x': 2, 'y': 4}]
x = [1, 2, 1, 3, 1, 4]

# brute force method
arr = []
for i in x:
  if not i in arr:
    arr.insert(x[i],i)

# recursive method
tmp = []
def remove_duplicates(j=0):
    if j < len(x):
      if not x[j] in tmp:
        tmp.append(x[j])
      i = j+1  
      remove_duplicates(i)

      

remove_duplicates()

1개의 라이너 리스트 이해:

values_non_duplicated = [value for index, value in enumerate(values) if value not in values[ : index]]

일상적으로 사용하는 경우 성능보다 미관을 중시하는 경우 내장 기능을 고려하십시오.pandas.Series.drop_duplicates:

    import pandas as pd
    import numpy as np

    uniquifier = lambda alist: pd.Series(alist).drop_duplicates().tolist()

    # from the chosen answer 
    def f7(seq):
        seen = set()
        seen_add = seen.add
        return [ x for x in seq if not (x in seen or seen_add(x))]

    alist = np.random.randint(low=0, high=1000, size=10000).tolist()

    print uniquifier(alist) == f7(alist)  # True

타이밍:

    In [104]: %timeit f7(alist)
    1000 loops, best of 3: 1.3 ms per loop
    In [110]: %timeit uniquifier(alist)
    100 loops, best of 3: 4.39 ms per loop

이 방법은 순서를 유지하고 O(n)시간 내에 실행됩니다.기본적으로 중복되는 것이 발견되면 구멍을 만들어 바닥에 가라앉히는 것입니다.는 읽기 및 쓰기 포인터를 사용합니다.중복이 발견될 때마다 읽기 포인터만 진행되며 쓰기 포인터는 중복된 엔트리에 남아 덮어씁니다.

def deduplicate(l):
    count = {}
    (read,write) = (0,0)
    while read < len(l):
        if l[read] in count:
            read += 1
            continue
        count[l[read]] = True
        l[write] = l[read]
        read += 1
        write += 1
    return l[0:write]

Import된 모듈 또는 세트를 사용하지 않는 솔루션:

text = "ask not what your country can do for you ask what you can do for your country"
sentence = text.split(" ")
noduplicates = [(sentence[i]) for i in range (0,len(sentence)) if sentence[i] not in sentence[:i]]
print(noduplicates)

출력:

['ask', 'not', 'what', 'your', 'country', 'can', 'do', 'for', 'you']

임플레이스 방식

모든 에 2차적인 입니다(이 정렬 됩니다).목록의 모든 요소에 대해 목록으로 선형 룩업이 있기 때문입니다(이 때문에 목록 재정렬 비용을 추가해야 합니다).del

단, 리스트의 끝에서 원점 방향으로 진행하면 왼쪽 서브리스트에 있는 각 용어를 삭제할 수 있습니다.

이 코드 아이디어는 단순합니다.

for i in range(len(l)-1,0,-1): 
    if l[i] in l[:i]: del l[i] 

간단한 구현 테스트

In [91]: from random import randint, seed                                                                                            
In [92]: seed('20080808') ; l = [randint(1,6) for _ in range(12)] # Beijing Olympics                                                                 
In [93]: for i in range(len(l)-1,0,-1): 
    ...:     print(l) 
    ...:     print(i, l[i], l[:i], end='') 
    ...:     if l[i] in l[:i]: 
    ...:          print( ': remove', l[i]) 
    ...:          del l[i] 
    ...:     else: 
    ...:          print() 
    ...: print(l)
[6, 5, 1, 4, 6, 1, 6, 2, 2, 4, 5, 2]
11 2 [6, 5, 1, 4, 6, 1, 6, 2, 2, 4, 5]: remove 2
[6, 5, 1, 4, 6, 1, 6, 2, 2, 4, 5]
10 5 [6, 5, 1, 4, 6, 1, 6, 2, 2, 4]: remove 5
[6, 5, 1, 4, 6, 1, 6, 2, 2, 4]
9 4 [6, 5, 1, 4, 6, 1, 6, 2, 2]: remove 4
[6, 5, 1, 4, 6, 1, 6, 2, 2]
8 2 [6, 5, 1, 4, 6, 1, 6, 2]: remove 2
[6, 5, 1, 4, 6, 1, 6, 2]
7 2 [6, 5, 1, 4, 6, 1, 6]
[6, 5, 1, 4, 6, 1, 6, 2]
6 6 [6, 5, 1, 4, 6, 1]: remove 6
[6, 5, 1, 4, 6, 1, 2]
5 1 [6, 5, 1, 4, 6]: remove 1
[6, 5, 1, 4, 6, 2]
4 6 [6, 5, 1, 4]: remove 6
[6, 5, 1, 4, 2]
3 4 [6, 5, 1]
[6, 5, 1, 4, 2]
2 1 [6, 5]
[6, 5, 1, 4, 2]
1 5 [6]
[6, 5, 1, 4, 2]

In [94]:                                                                                                                             

언급URL : https://stackoverflow.com/questions/480214/how-do-i-remove-duplicates-from-a-list-while-preserving-order

반응형