programing

반복하는 동안 목록에서 항목을 제거하려면 어떻게 해야 합니까?

bestcode 2022. 12. 7. 22:31
반응형

반복하는 동안 목록에서 항목을 제거하려면 어떻게 해야 합니까?

Python에서 Tuples 목록을 반복하고 있으며, 특정 기준에 부합하는 경우 제거하려고 합니다.을 제거하려고 합니다.

for tup in somelist:
    if determine(tup):
         code_to_remove_tup

★★★★★★★★★★★★★ 대신 무엇을 사용하면 요?code_to_remove_tup이 방법으로 아이템을 제거하는 방법을 알 수 없습니다.

목록 이해를 사용하여 제거하지 않을 요소만 포함하는 새 목록을 만들 수 있습니다.

somelist = [x for x in somelist if not determine(x)]

슬라이스에 somelist[:]기존 목록을 원하는 항목만 포함하도록 변환할 수 있습니다.

somelist[:] = [x for x in somelist if not determine(x)]

은 다른 때 이 될 수 있습니다.somelist변경 사항을 반영해야 합니다.

이해력 '어울리다', '어울리다', '어울리다'를 사용할 .itertools2 :。 Python 2:

from itertools import ifilterfalse
somelist[:] = ifilterfalse(determine, somelist)

또는 Python 3의 경우:

from itertools import filterfalse
somelist[:] = filterfalse(determine, somelist)

목록 통합을 제안하는 답변은 완전히 새로운 목록을 작성한 후 이전 목록을 수정하지 않는 것과 동일한 이름을 붙인다는 점을 제외하고는 거의 정확합니다.이는 @Lennart의 제안과 같이 선택적 삭제와 달리 고속이지만 여러 참조를 통해 목록에 액세스할 경우 목록 객체 자체를 변경하지 않고 참조 중 하나를 다시 설치하는 것만으로 인해 미묘하고 치명적인 버그가 발생할 수 있습니다.

다행히 목록 수집 속도와 일괄 변경에 필요한 의미를 모두 쉽게 얻을 수 있습니다. 코드만 있으면 됩니다.

somelist[:] = [tup for tup in somelist if determine(tup)]

다른 답변과의 미묘한 차이점에 주의해 주세요.이것은 배너명에 할당하는 것이 아닙니다.이것은 다른 답변과 같이 하나의 참조(이전 리스트 오브젝트에서 새로운 리스트 오브젝트로)를 재지정하는 것이 아니라, 우연히 전체 리스트가 되는 리스트 슬라이스에 할당하는 것입니다.

먼저 목록 복사본을 가져와 반복해야 합니다. 그렇지 않으면 반복이 실패하고 예기치 않은 결과가 발생할 수 있습니다.

예를 들어 (목록 유형에 따라 다름):

for tup in somelist[:]:
    etc....

예:

>>> somelist = range(10)
>>> for x in somelist:
...     somelist.remove(x)
>>> somelist
[1, 3, 5, 7, 9]

>>> somelist = range(10)
>>> for x in somelist[:]:
...     somelist.remove(x)
>>> somelist
[]
for i in range(len(somelist) - 1, -1, -1):
    if some_condition(somelist, i):
        del somelist[i]

거꾸로 가야 합니다.그렇지 않으면 지금 앉아 있는 나뭇가지를 톱으로 자르는 것과 같습니다:-)

2 Python 2 치환: " "range타타에 xrange 리스트

회피책의 개요

다음 중 하나:

  • 링크 리스트의 실장/롤링을 사용합니다.

    링크된 목록은 효율적인 항목 제거를 지원하는 적절한 데이터 구조이며 공간/시간 균형을 유지하도록 강요하지 않습니다.

    A CPythonlist는 여기서 설명한 바와 같이 다이내믹 어레이와 함께 구현되어 있습니다.이러한 데이터 유형은 삭제를 지원하기에 적합하지 않습니다.

    그러나 표준 라이브러리에는 링크된 목록이 없는 것 같습니다.

  • 출발을 하다list().append()https://stackoverflow.com/a/1207460/895245 에서 설명한 바와 같이 마지막에 다시 접속해 주세요.

    이 방법은 시간은 효율적이지만 반복 중에 어레이의 복사본을 추가로 보관하기 때문에 공간 효율은 떨어집니다.

  • del다음 URL에서 설명한 인덱스를 사용하여 https://stackoverflow.com/a/1207485/895245를 참조하십시오.

    이는 어레이 복사를 처리하기 때문에 공간 효율은 높지만 동적 어레이에서 삭제하면 다음 모든 항목을 O(N) 단위로 되돌려야 하기 때문에 시간 효율은 낮습니다.

방법으로 LinkedList 더 빠른 것을 ..append()메모리가 큰 문제가 되지 않는 한 디폴트 옵션입니다.

공식 Python 2 튜토리얼 4.2. "문장용"

https://docs.python.org/2/tutorial/controlflow.html#for-statements

이 문서에서는 다음 사항을 명확히 하고 있습니다.

  • 수정하려면 반복 목록의 복사본을 만들어야 합니다.
  • 입니다.[:]

루프내에서 반복하는 순서를 변경할 필요가 있는 경우(예를 들면, 선택한 항목을 복제하는 경우)에는, 우선 카피를 작성하는 것을 추천합니다.시퀀스를 반복해도 복사는 암묵적으로 작성되지 않습니다.슬라이스 표기법을 사용하면 특히 편리합니다.

>>> words = ['cat', 'window', 'defenestrate']
>>> for w in words[:]:  # Loop over a slice copy of the entire list.
...     if len(w) > 6:
...         words.insert(0, w)
...
>>> words
['defenestrate', 'cat', 'window', 'defenestrate']

Python 2 설명서 7.3. "The for statement"

https://docs.python.org/2/reference/compound_stmts.html#for

문서의 이 부분에서는 복사본을 작성해야 한다고 다시 한 번 설명하고 실제 제거 예를 보여 줍니다.

주의: 루프에 의해 시퀀스가 수정될 때는 미묘함이 있습니다(이는 가변 시퀀스(리스트 등)에 대해서만 발생합니다).내부 카운터는 다음에 사용되는 항목을 추적하기 위해 사용되며, 반복할 때마다 증가합니다.이 카운터가 시퀀스 길이에 도달하면 루프가 종료됩니다.즉, 스위트가 현재(또는 이전) 항목을 시퀀스에서 삭제하면 이미 처리된 현재 항목의 인덱스를 가져오므로 다음 항목은 건너뜁니다.마찬가지로 스위트가 현재 항목 앞에 항목을 삽입하면 다음 번 루프를 통해 현재 항목이 다시 처리됩니다.이로 인해 전체 시퀀스의 슬라이스를 사용하여 임시 복사를 함으로써 다음과 같은 심각한 오류를 방지할 수 있습니다.

for x in a[:]:
    if x < 0: a.remove(x)

저는 이 구현에 합니다. 는, 는, 는, 는, 는, however, however, however, however, however, however, however, however, however, however, however, however, however however.remove()값을 찾으려면 목록 전체를 반복해야 합니다.

Python이 더 잘할 수 있을까?

이 특정 Python API는 개선될 수 있을 것 같습니다.예를 들어 다음과 같이 비교해 보십시오.

  • Java ListIterator:: " 콜은 다음 콜 또는 이전 콜에 대해 한 번만 발신할 수 있습니다" 문서를 삭제합니다.
  • C++: 요소 제거 후 요소에 유효한 인터레이터를 반환합니다.

둘 다 반복하는 목록을 수정할 수 없다는 것을 명확히 하고 목록을 복사하지 않고 효율적으로 수정할 수 있는 방법을 제공합니다.

아마도 근본적인 근거는 Python 목록이 동적 어레이를 지원한다고 가정하고, 따라서 어떤 유형의 제거라도 시간 효율이 떨어집니다. 반면 Java는 다음과 같은 두 가지 모두와 구현으로 더 나은 인터페이스 계층을 가지고 있습니다.ListIterator.

Python stdlib에도 명시적인 링크 리스트 타입이 없는 것 같습니다.Python Linked List

이러한 예에 대한 최선의 접근법은 목록을 이해하는 것입니다.

somelist = [tup for tup in somelist if determine(tup)]

보다 더 일을 determine새로운 리스트를 작성하고, 간단하게 추가하는 것을 선호합니다.를 들면, 「」

newlist = []
for tup in somelist:
    # lots of code here, possibly setting things up for calling determine
    if determine(tup):
        newlist.append(tup)
somelist = newlist

를 사용한 복사remove아래 답변 중 하나에서 설명한 바와 같이 코드가 좀 더 깔끔하게 보일 수 있습니다.를 카피하는 에, 「」의 에, 매우 큰하지 말아 주세요.O(n) remove되는 각 을 실시합니다.이 「」가 됩니다.O(n^2)알고리즘.

for tup in somelist[:]:
    # lots of code here, possibly setting things up for calling determine
    if determine(tup):
        newlist.append(tup)

기능 프로그래밍을 좋아하는 사용자:

somelist[:] = filter(lambda tup: not determine(tup), somelist)

또는

from itertools import ifilterfalse
somelist[:] = list(ifilterfalse(determine, somelist))

방대한 리스트로 이것을 할 필요가 있었고, 리스트의 중복은 비용이 많이 드는 것 같았습니다.특히 저 같은 경우는 남아 있는 아이템에 비해 삭제 건수가 적기 때문입니다.저는 이 낮은 수준의 접근을 취했습니다.

array = [lots of stuff]
arraySize = len(array)
i = 0
while i < arraySize:
    if someTest(array[i]):
        del array[i]
        arraySize -= 1
    else:
        i += 1

몇 번의 삭제가 큰 목록을 복사하는 것에 비해 얼마나 효과적인지 모르겠습니다.의견이 있으시면 코멘트 부탁드립니다.

이 답변의 대부분은 목록 복사본을 만들기를 원합니다.리스트가 꽤 길어서(11만 아이템) 계속 줄이는 것이 현명했던 유스케이스가 있었습니다.

우선 포어치 루프를 while 루프로 대체해야 합니다.

i = 0
while i < len(somelist):
    if determine(somelist[i]):
         del somelist[i]
    else:
        i += 1

「」의 값i이전 항목이 삭제되면 새 항목의 값을 THE SAME INDEX에서 가져오게 되므로 if 블록에서는 변경되지 않습니다.

현재 목록 항목이 원하는 조건을 충족하는 경우 새 목록을 만드는 것이 현명할 수 있습니다.

따라서:

for item in originalList:
   if (item != badValue):
        newList.append(item)

프로젝트 전체를 새 목록 이름으로 다시 코드화할 필요가 없습니다.

originalList[:] = newList

참고: Python 문서:

copy.copy(x) x의 얕은 복사본을 반환합니다.

copy.deepcopy(x) x의 딥 복사본을 반환합니다.

이 답변은 원래 중복으로 표시된 질문에 대한 응답으로 작성되었습니다.python의 목록에서 좌표 제거

코드에는 다음 두 가지 문제가 있습니다.

1) remove()를 사용할 때는 정수를 제거하려고 하지만 태플을 제거해야 합니다.

2) for 루프는 목록 내의 항목을 건너뜁니다.

코드를 실행하면 어떤 일이 일어나는지 살펴보겠습니다.

>>> L1 = [(1,2), (5,6), (-1,-2), (1,-2)]
>>> for (a,b) in L1:
...   if a < 0 or b < 0:
...     L1.remove(a,b)
... 
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
TypeError: remove() takes exactly one argument (2 given)

첫 번째 문제는 삭제()에 'a'와 'b'를 모두 전달하지만 remove()는 단일 인수만 받아들인다는 것입니다.그러면 어떻게 하면 목록과 함께 제대로 작동하도록 할 수 있을까요?리스트의 각 요소가 무엇인지 알아내야 합니다.이 경우 각각이 태플입니다.이것을 확인하려면 , 리스트의 1개의 요소에 액세스 합니다(인덱싱은 0부터 시작합니다).

>>> L1[1]
(5, 6)
>>> type(L1[1])
<type 'tuple'>

아하! L1의 각 요소는 사실 태플입니다.이것이 바로 삭제하기 위해 필요한 것입니다( ).python의 tuples는 매우 간단합니다. 단순히 괄호로 값을 묶어서 만듭니다."a, b"는 태플은 아니지만 "(a, b)"는 태플이다.따라서 코드를 수정하고 다시 실행합니다.

# The remove line now includes an extra "()" to make a tuple out of "a,b"
L1.remove((a,b))

이 코드는 오류 없이 실행되지만 출력되는 목록을 확인합니다.

L1 is now: [(1, 2), (5, 6), (1, -2)]

왜 (1,-2)가 아직 당신의 리스트에 있나요?루프를 사용하여 반복하면서 목록을 수정하는 것은 특별한 주의 없이 매우 나쁜 생각인 것으로 나타났습니다.(1, -2)이 목록에 남아 있는 이유는 목록 내의 각 항목의 위치가 for 루프의 반복 사이에 변경되었기 때문입니다.위의 코드를 더 긴 목록으로 입력하면 어떻게 되는지 살펴보겠습니다.

L1 = [(1,2),(5,6),(-1,-2),(1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
### Outputs:
L1 is now: [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]

이 결과에서 알 수 있듯이 조건문이 true로 평가되고 목록 항목이 삭제될 때마다 루프의 다음 반복은 목록의 다음 항목에 대한 평가를 건너뜁니다.그 값은 현재 다른 인덱스에 배치되어 있기 때문입니다.

가장 직관적인 해결책은 목록을 복사한 다음 원래 목록을 반복하고 복사본만 수정하는 것입니다.다음과 같이 시도해 볼 수 있습니다.

L2 = L1
for (a,b) in L1:
    if a < 0 or b < 0 :
        L2.remove((a,b))
# Now, remove the original copy of L1 and replace with L2
print L2 is L1
del L1
L1 = L2; del L2
print ("L1 is now: ", L1)

단, 출력은 이전과 동일합니다.

'L1 is now: ', [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]

이는 L2를 만들 때 python이 실제로 새로운 개체를 만들지 않았기 때문입니다.대신 L2를 L1과 같은 오브젝트로 참조했을 뿐입니다.이것은 단순한 「is」(==)와는 다른 「is」로 확인할 수 있습니다.

>>> L2=L1
>>> L1 is L2
True

copy.copy()를 사용하여 실제 복사본을 만들 수 있습니다.그러면 모든 것이 예상대로 작동합니다.

import copy
L1 = [(1,2), (5,6),(-1,-2), (1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
L2 = copy.copy(L1)
for (a,b) in L1:
    if a < 0 or b < 0 :
        L2.remove((a,b))
# Now, remove the original copy of L1 and replace with L2
del L1
L1 = L2; del L2
>>> L1 is now: [(1, 2), (5, 6), (3, 4), (5, 7), (2, 1), (0, 6)]

마지막으로 L1의 완전히 새로운 복사본을 만드는 것보다 더 깨끗한 솔루션이 있습니다.reverse() 함수는 다음과 같습니다.

L1 = [(1,2), (5,6),(-1,-2), (1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
for (a,b) in reversed(L1):
    if a < 0 or b < 0 :
        L1.remove((a,b))
print ("L1 is now: ", L1)
>>> L1 is now: [(1, 2), (5, 6), (3, 4), (5, 7), (2, 1), (0, 6)]

유감스럽지만 reverse()가 어떻게 동작하는지는 충분히 설명할 수 없습니다.목록이 전달되면 'listreverseitator' 개체를 반환합니다.실제적인 목적을 위해, 당신은 그것을 그 주장의 역복사를 만든다고 생각할 수 있다.이것이 제가 추천하는 해결책입니다.

반복 중에 목록에서 요소를 삭제하려면 삭제 후 현재 인덱스와 종료 인덱스를 변경할 수 있도록 while-loop을 사용합니다.

예를 들어:

i = 0
length = len(list1)

while i < length:
    if condition:
        list1.remove(list1[i])
        i -= 1
        length -= 1

    i += 1

반복 중에 다른 작업을 수행하려면 인덱스(예를 들어 dits 목록이 있는 경우 참조할 수 있음)와 실제 목록 항목 내용을 모두 가져오는 것이 좋습니다.

inlist = [{'field1':10, 'field2':20}, {'field1':30, 'field2':15}]    
for idx, i in enumerate(inlist):
    do some stuff with i['field1']
    if somecondition:
        xlist.append(idx)
for i in reversed(xlist): del inlist[i]

enumerate를 사용하면 항목과 인덱스에 한 번에 액세스할 수 있습니다. reversed나중에 삭제할 인덱스가 변경되지 않도록 하는 것입니다.

몇 가지 사항을 제거할 뿐만 아니라 모든 요소를 단일 루프에 포함하는 작업을 수행할 때 유용한 하나의 가능한 해결책입니다.

alist = ['good', 'bad', 'good', 'bad', 'good']
i = 0
for x in alist[:]:
    if x == 'bad':
        alist.pop(i)
        i -= 1
    # do something cool with x or just print x
    print(x)
    i += 1

for 루프는 인덱스를 통해 반복됩니다.

리스트가 있다고 생각하고

[5, 7, 13, 29, 65, 91]

라는 것을 합니다.lis★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★♪

당신의 변수

lis = [5, 7, 13, 29, 35, 65, 91]
       0  1   2   3   4   5   6

5회 반복 중에

당신의 숫자 35는 소수점이 아니어서 리스트에서 삭제했습니다.

lis.remove(y)

다음(65)은 이전 인덱스로 이동합니다.

lis = [5, 7, 13, 29, 65, 91]
       0  1   2   3   4   5

그래서 4번째 반복 포인터가 5번째 반복으로 이동했다.

이전 인덱스로 이동한 이후 루프가 65를 커버하지 않는 이유입니다.

따라서 목록을 복사 대신 원본 변수를 참조하는 다른 변수로 참조해서는 안 됩니다.

ite = lis #dont do it will reference instead copy

목록 list[::]

이제 넌 줄거야

[5, 7, 13, 29]

문제는 반복 중에 목록에서 값을 삭제하면 목록 인덱스가 축소된다는 것입니다.

이해력을 시험해 보세요.

리스트, 태플, 딕트, 스트링 등 반복 가능한 모든 것을 지원하는

다른 답변은 반복 중인 목록에서 삭제하는 것이 일반적으로 좋지 않다는 것입니다.은 몇 할 수 어렵기 에 보통 또는 목록 이해, 목록 이해, 목록 분석 등을 하는 것이 filter.

그러나 반복하는 시퀀스에서 요소를 제거하는 것이 안전한 경우가 한 가지 있습니다. 반복하는 동안 항목을 하나만 제거하는 경우입니다.이것은, 다음의 방법으로 확인할 수 있습니다.return ★★★break §:

for i, item in enumerate(lst):
    if item % 4 == 0:
        foo(item)
        del lst[i]
        break

이 방법은 어떤 조건을 충족하는 목록의 첫 번째 항목에 부작용이 있는 작업을 수행한 후 바로 목록에서 해당 항목을 제거하는 경우 목록 이해보다 이해하기 쉽습니다.

하면 것 요.filter()빌트인으로서 이용 가능합니다.

상세한 것에 대하여는, 여기를 봐주세요.

for-looping을 역방향으로 시도하면 다음과 같은 작업을 수행할 수 있습니다.

list_len = len(some_list)
for i in range(list_len):
    reverse_i = list_len - 1 - i
    cur = some_list[reverse_i]

    # some logic with cur element

    if some_condition:
        some_list.pop(reverse_i)

이렇게 하면 인덱스가 정렬되고 목록 업데이트가 수행되지 않습니다(커 요소를 팝할지 여부에 관계없이).

입니다. 이 자신의 물론 '아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아iterator through를 통해.filter.

Filter이치노 Filter각 후이 '유지'인지 ''인지에 를 결정합니다.True ★★★★★★★★★★★★★★★★★」False.

예를 들어 다음과 같습니다(태플에 승산이 있음).

list(filter(lambda x:x%2==1, (1, 2, 4, 5, 6, 9, 10, 15)))  
# result: [1, 5, 9, 15]

주의:반복기도 처리할 수 없습니다.반복자가 시퀀스보다 좋을 수 있습니다.

비슷한 작업을 수행해야 했는데, 제 경우에는 메모리가 문제였습니다. 즉, 목록 내에서 여러 데이터 세트 개체를 몇 가지 작업을 수행한 후 새 개체로 병합해야 했고, 병합하는 각 항목을 삭제하여 모든 항목이 중복되거나 메모리가 소진되는 것을 방지해야 했습니다.내 경우 오브젝트를 리스트가 아닌 사전에 저장하면 정상적으로 동작합니다.

```

k = range(5)
v = ['a','b','c','d','e']
d = {key:val for key,val in zip(k, v)}

print d
for i in range(5):
    print d[i]
    d.pop(i)
print d

```

TLDR:

이 작업을 수행할 수 있는 라이브러리를 작성했습니다.

from fluidIter import FluidIterable
fSomeList = FluidIterable(someList)  
for tup in fSomeList:
    if determine(tup):
        # remove 'tup' without "breaking" the iteration
        fSomeList.remove(tup)
        # tup has also been removed from 'someList'
        # as well as 'fSomeList'

가능하면 반복하면서 반복할 필요가 없는 다른 방법을 사용하는 것이 가장 좋지만, 알고리즘에 따라서는 그렇게 간단하지 않을 수도 있습니다.따라서 원래 질문에서 설명한 코드 패턴을 정말로 원하는 경우 가능합니다.

목록뿐만 아니라 모든 가변 시퀀스에서 작동해야 합니다.


완전한 답변:

편집: 이 답변의 마지막 코드 예에서는 목록 이해를 사용하는 대신 목록을 수정해야 하는 이유를 설명합니다.답변의 첫 번째 부분은 어레이를 수정하는 방법에 대한 튜토리얼 역할을 합니다.

이 답변은 (관련 질문에 대한) senderle로부터의 답변으로 이어집니다.수정된 목록을 반복하는 동안 어레이 인덱스가 어떻게 업데이트되는지 설명합니다.다음 솔루션은 목록이 변경되어도 어레이 인덱스를 올바르게 추적하도록 설계되어 있습니다.

.fluidIter.py여기서부터 https://github.com/alanbacon/FluidIterator하나의 파일이기 때문에 git을 설치할 필요가 없습니다.설치 프로그램이 없으므로 파일이 직접 python 경로에 있는지 확인해야 합니다.2에서는 되지 않았습니다.

from fluidIter import FluidIterable
l = [0,1,2,3,4,5,6,7,8]  
fluidL = FluidIterable(l)                       
for i in fluidL:
    print('initial state of list on this iteration: ' + str(fluidL)) 
    print('current iteration value: ' + str(i))
    print('popped value: ' + str(fluidL.pop(2)))
    print(' ')

print('Final List Value: ' + str(l))

그러면 다음과 같은 출력이 생성됩니다.

initial state of list on this iteration: [0, 1, 2, 3, 4, 5, 6, 7, 8]
current iteration value: 0
popped value: 2

initial state of list on this iteration: [0, 1, 3, 4, 5, 6, 7, 8]
current iteration value: 1
popped value: 3

initial state of list on this iteration: [0, 1, 4, 5, 6, 7, 8]
current iteration value: 4
popped value: 4

initial state of list on this iteration: [0, 1, 5, 6, 7, 8]
current iteration value: 5
popped value: 5

initial state of list on this iteration: [0, 1, 6, 7, 8]
current iteration value: 6
popped value: 6

initial state of list on this iteration: [0, 1, 7, 8]
current iteration value: 7
popped value: 7

initial state of list on this iteration: [0, 1, 8]
current iteration value: 8
popped value: 8

Final List Value: [0, 1]

에서는요, 이렇게 요.popFluid List (유체 목록) 밖에도 할 수 , 를 들어 음음음음 are are are are are are are are are are are are are are are are are are are are are are are are are are are are are are are are are are .del fluidL[i],.remove,.insert,.append,.extend은 슬라이스슬라이스)를 도 있습니다sort ★★★★★★★★★★★★★★★★★」reverse(미국의

, .fluidL ★★★★★★★★★★★★★★★★★」l코드가 작동하지 않는 다른 목록 개체에 재할당되었습니다. ★★★★★★★★★★★★★★★.fluidL오브젝트는 여전히 for 루프에 의해 사용되지만 수정할 수 있는 범위를 벗어납니다.

예.

fluidL[2] = 'a'   # is OK
fluidL = [0, 1, 'a', 3, 4, 5, 6, 7, 8]  # is not OK

목록의 현재 인덱스 값에 액세스하려면 열거를 사용할 수 없습니다.이는 for 루프가 실행된 횟수만 계산하기 때문입니다.대신 반복기 개체를 직접 사용합니다.

fluidArr = FluidIterable([0,1,2,3])
# get iterator first so can query the current index
fluidArrIter = fluidArr.__iter__()
for i, v in enumerate(fluidArrIter):
    print('enum: ', i)
    print('current val: ', v)
    print('current ind: ', fluidArrIter.currentIndex)
    print(fluidArr)
    fluidArr.insert(0,'a')
    print(' ')

print('Final List Value: ' + str(fluidArr))

다음과 같이 출력됩니다.

enum:  0
current val:  0
current ind:  0
[0, 1, 2, 3]

enum:  1
current val:  1
current ind:  2
['a', 0, 1, 2, 3]

enum:  2
current val:  2
current ind:  4
['a', 'a', 0, 1, 2, 3]

enum:  3
current val:  3
current ind:  6
['a', 'a', 'a', 0, 1, 2, 3]

Final List Value: ['a', 'a', 'a', 'a', 0, 1, 2, 3]

FluidIterable객체에 래퍼를 합니다.class는 원래 목록 객체에 대한 를 제공합니다.는 다음과할 수 .

originalList = fluidArr.fixedIterable

예는 "/"를 하십시오.if __name__ is "__main__":의 섹션fluidIter.py이것들은 다양한 상황에서 무슨 일이 일어나는지 설명해주기 때문에 살펴볼 가치가 있다.예: 슬라이스를 사용하여 목록의 큰 섹션을 바꿉니다.또는 루프에 대해 중첩된 동일한 반복 가능을 사용(및 수정)합니다.

처음에 말씀드렸듯이, 이것은 코드의 가독성을 해치고 디버깅을 더 어렵게 하는 복잡한 솔루션입니다.따라서 David Raznick의 답변에서 언급된 목록 포괄과 같은 다른 해결책을 먼저 고려해야 합니다.그러나 삭제가 필요한 요소의 인덱스를 추적하는 것보다 이 클래스가 나에게 유용하고 사용하기 쉬웠던 적이 있습니다.


편집: 코멘트에서 설명한 바와 같이 이 답변은 이 접근방식이 해결책을 제공하는 데 문제가 되지 않습니다.이 점에 대해서는 여기서 설명하겠습니다.

목록 통합은 새 목록을 생성하는 방법을 제공하지만 이러한 접근 방식은 목록의 현재 상태가 아닌 각 요소를 분리하여 보는 경향이 있습니다.

예.

newList = [i for i in oldList if testFunc(i)]

에 그 ?testFunc에 .newList ? 아니면 still에 있는 oldList음음음음음 음음음?리스트 이해는 아직 사용할 수 있지만, 우아함을 잃기 시작하고, 저는 리스트를 수정하는 것이 더 쉬워집니다.

다음 코드는 위의 문제를 겪고 있는 알고리즘의 한 예입니다.이 알고리즘은 다른 요소의 배수가 되지 않도록 목록을 축소합니다.

randInts = [70, 20, 61, 80, 54, 18, 7, 18, 55, 9]
fRandInts = FluidIterable(randInts)
fRandIntsIter = fRandInts.__iter__()
# for each value in the list (outer loop)
# test against every other value in the list (inner loop)
for i in fRandIntsIter:
    print(' ')
    print('outer val: ', i)
    innerIntsIter = fRandInts.__iter__()
    for j in innerIntsIter:
        innerIndex = innerIntsIter.currentIndex
        # skip the element that the outloop is currently on
        # because we don't want to test a value against itself
        if not innerIndex == fRandIntsIter.currentIndex:
            # if the test element, j, is a multiple 
            # of the reference element, i, then remove 'j'
            if j%i == 0:
                print('remove val: ', j)
                # remove element in place, without breaking the
                # iteration of either loop
                del fRandInts[innerIndex]
            # end if multiple, then remove
        # end if not the same value as outer loop
    # end inner loop
# end outerloop

print('')
print('final list: ', randInts)

출력 및 최종 축소 목록은 다음과 같습니다.

outer val:  70

outer val:  20
remove val:  80

outer val:  61

outer val:  54

outer val:  18
remove val:  54
remove val:  18

outer val:  7
remove val:  70

outer val:  55

outer val:  9
remove val:  18

final list:  [20, 61, 7, 55, 9]

한 번에 한 항목만 필터링하는 것이 아니라 반복하는 동안 반복을 변경해야 하는 경우도 있습니다.

다음 예에서는 미리 목록을 복사하는 것이 잘못되어 있고, 역방향 반복이 불가능하며, 목록 이해도 선택사항이 아닌 경우를 보여 줍니다.

""" Sieve of Eratosthenes """

def generate_primes(n):
    """ Generates all primes less than n. """
    primes = list(range(2,n))
    idx = 0
    while idx < len(primes):
        p = primes[idx]
        for multiple in range(p+p, n, p):
            try:
                primes.remove(multiple)
            except ValueError:
                pass #EAFP
        idx += 1
        yield p

저는 당신의 문제를 해결하기 위한 세 가지 방법을 생각할 수 있습니다.를 들어, 저는 목록을 하겠습니다.somelist = [(1,2,3), (4,5,6), (3,6,6), (7,8,9), (15,0,0), (10,11,12)]가 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★.sum of elements of a tuple = 15마지막 목록에는 합계가 15가 아닌 튜플만 있습니다.

제가 고른 것은 무작위로 뽑은 예시입니다.튜플 리스트와 제가 선택한 조건자유롭게 변경해 주세요.

방법 1.> 제안한 프레임워크를 사용합니다(for loop 내의 코드를 입력합니다).작은 코드를 사용하고 있습니다.del위의 조건을 충족하는 태플을 삭제합니다.단, 이 메서드는 연속해서 배치된2개의 튜플이 지정된 조건을 충족하면 (상기 조건을 만족시키는) 태플을 놓칩니다.

for tup in somelist:
    if ( sum(tup)==15 ): 
        del somelist[somelist.index(tup)]

print somelist
>>> [(1, 2, 3), (3, 6, 6), (7, 8, 9), (10, 11, 12)]

방법 2.> 지정된 조건이 충족되지 않는 요소(튜플)를 포함하는 새 목록을 작성합니다(이것은 지정된 조건이 충족되는 목록의 요소를 삭제하는 것과 같습니다).그 코드는 다음과 같습니다.

newlist1 = [somelist[tup] for tup in range(len(somelist)) if(sum(somelist[tup])!=15)]

print newlist1
>>>[(1, 2, 3), (7, 8, 9), (10, 11, 12)]

방법 3.> 지정된 조건을 만족하는 인덱스를 찾아 해당 인덱스에 대응하는 요소(튜플)를 삭제합니다.그 코드는 다음과 같습니다.

indices = [i for i in range(len(somelist)) if(sum(somelist[i])==15)]
newlist2 = [tup for j, tup in enumerate(somelist) if j not in indices]

print newlist2
>>>[(1, 2, 3), (7, 8, 9), (10, 11, 12)]

방법 1과 방법 2가 방법 3보다 빠릅니다.method1보다 method2 및 method3가 효율적입니다.나는 방법2가 더 좋다.앞서 말한 예에서는time(method1) : time(method2) : time(method3) = 1 : 1 : 1.7

나중에 새 목록을 사용할 경우 elem을 None으로 설정하고 다음과 같이 나중에 루프로 판단하면 됩니다.

for i in li:
    i = None

for elem in li:
    if elem is None:
        continue

이렇게 하면 목록을 복사할 필요가 없고 이해하기 쉽습니다.

큰 가능성이 있는 것은, 이하와 같이 사용합니다.

import numpy as np

orig_list = np.array([1, 2, 3, 4, 5, 100, 8, 13])

remove_me = [100, 1]

cleaned = np.delete(orig_list, remove_me)
print(cleaned)

그것은 다른 어떤 것보다도 상당히 빠를 것이다.

언급URL : https://stackoverflow.com/questions/1207406/how-to-remove-items-from-a-list-while-iterating

반응형