문제

이 질문은 이미 있는 대답을 여기:

내가 쓰는 코드 라이브러리는 모두 지원되며,내가 종종 필요한 항목을 제거하는 목록에서 또는 다른 시퀀스 입력에 따라 기준입니다.지 못한 해결책을 발견되는 우아하고 효율적으로 항목을 제거하는 목록에서 현재 반복은 나쁜 것입니다.예를 들어,이 작업을 할 수 없습니다:

for name in names:
    if name[-5:] == 'Smith':
        names.remove(name)

나는 일반적으로 끝나 뭔가를 하는 다음과 같다:

toremove = []
for name in names:
    if name[-5:] == 'Smith':
        toremove.append(name)
for name in toremove:
    names.remove(name)
del toremove

이 innefficient,상당히 추하고 가능하게 버그(어떻게 여러 개를 처리할 수 있는'존 스미스'항목?).누군가가 더 우아한 솔루션으로,또는 적어도 더 효율적으로 하나?

는 방법에 대해 중 하나는 작품으로도 할 수 있습니다.

도움이 되었습니까?

해결책

두 쉽게 달성하는 방법에만 필터링되:

  1. filter:

    names = filter(lambda name: name[-5:] != "Smith", names)

  2. 를 사용하여 목록을 함축:

    names = [name for name in names if name[-5:] != "Smith"]

참고는 모두의 경우 값을 유지하는 조건자의 기능을 평가하여 True, 는,그래서 당신은 반대로 논리(즉당신이 말하는"지키지 않는 사람들이 마지막 이름 Smith"대신에"제거하는 사람들 마지막 이름 Smith").

편집 재미있는...두 사람이 개별적으로 게시 모두의 답변을 제안했으로 나가 게시 광산이다.

다른 팁

할 수도 있습니다 반복하여 거꾸로 위 목록:

for name in reversed(names):
    if name[-5:] == 'Smith':
        names.remove(name)

이는 장점을 가지고 있는 만들어지지 않습니다 새로운 목록(아 filter 또는 목록의 이해)사용 반복기 대신의 목록 사본(아 [:]).

참고 하지만 요소를 제거하는 동안 반복 뒤로 안전 삽입하는 그들은 다소 난이도합니다.

분명한 대답을 하는 요한과 몇 가지 다른 사람들,즉:

>>> names = [name for name in names if name[-5:] != "Smith"]       # <-- slower

하지만 그는 단점이 있다 새로 만들고 목록의 개체,보다는 오히려 다시 사용하면 원래 개체.나는 몇 가지 프로파일링 및 실험,그리고 가장 효율적인 방법이 나온다:

>>> names[:] = (name for name in names if name[-5:] != "Smith")    # <-- faster

에 할당"이름:]"기본적으로 의미"의 내용을 대체하기에 이름 목록 다음과 같은 가치".그것이터 할당을 이름에는 그것이 만들어지지 않습니다 새로운 목록 개체입니다.의 오른쪽에 할당 발전기 식(주 괄호를 사용하여 보다는 오히려 대괄호).이 Python 을 반복하러 목록입니다.

일부는 빠른 프로파일링을 제안이 약 30%보다 더 빨리 목록이 이해에 접근,그리고 약 40%더 빠르게 필터 접근 방식이다.

주의:이 솔루션을 보다 빠르게 확실한 해결책,그것은 더 어둡고에 의존하여 더 많은 고급 Python 기술입니다.당신이 그것을 사용하는 경우에,나는 추천 동반으로합니다.그것은 아마만 사용할 가치가 있는 경우에 당신은 당신이 정말로 걱정하의 성능이 특정 작업(는 매우 빨리 상관 없이).(경우에는 내가 사용하는 이,리*빔 검색 및 사용 이를 제거하는 지점 검색에서 검색 빔입니다.)

목록 이해

list = [x for x in list if x[-5:] != "smith"]

거기에 시간 경우 필터링(필터를 사용하거나 또는 목록의 이해)작동하지 않습니다.이 때 발생하는 몇 가지 다른 객체에 대한 참조 목록에 당신을 수정하고 수정할 필요가 있 목록에서 장소입니다.

for name in names[:]:
    if name[-5:] == 'Smith':
        names.remove(name)

유일한 차이의 원래 코드의 사용 names[:]names 에 대한 반복입니다.는 방법으로드 반복하는(얕은)목록의 사본을하고 제거가 정상적으로 작동합니다.이 목록에 복사하는 얕은,그것은 매우 빠르다.

필터가 될 것이 굉장하다.간단한 예제:

names = ['mike', 'dave', 'jim']
filter(lambda x: x != 'mike', names)
['dave', 'jim']

편집: 코리의 목록을 이해력을 구축 할 수 있습니다..

names = filter(lambda x: x[-5:] != "Smith", names);

모두 솔루션 필터이해 필요한 건물은 새로운 목록입니다.나는 알 수 없는 충분한의 내부를 확인하기 위해,그러나 나 생각 는 전통적인(지만 우아한)접근할 수 있는 더 효율적인:

names = ['Jones', 'Vai', 'Smith', 'Perez']

item = 0
while item <> len(names):
    name = names [item]
    if name=='Smith':
        names.remove(name)
    else:
        item += 1

print names

어쨌든 짧은 목록에,나는 하나의 두 가지 솔루션을 제안했다.

귀하의 질문에 대답을 작업에 대한 사전 주의 해야 한 Python3.0 이 포함됩 dict 함축:

>>> {i : chr(65+i) for i in range(4)}

말은 시간에,당신이 할 수 있는 준 dict 이해 이 방법:

>>> dict([(i, chr(65+i)) for i in range(4)])

또는 더 직접적인 응답:

dict([(key, name) for key, name in some_dictionary.iteritems if name[-5:] != 'Smith'])

는 경우 목록 해야 될 필터링에서는 이러한 목록의 크기는 매우 크고,다음 알고리즘에서 언급된 이전 답변을 기반으로 목록입니다.remove()적합하지 않기 때문에,자신의 계산적 복잡도 O(n^2).이 경우에는 사용할 수 있습니다 다음과 같은 없다-그래서 pythonic 기능:

def filter_inplace(func, original_list):
  """ Filters the original_list in-place.

  Removes elements from the original_list for which func() returns False.

  Algrithm's computational complexity is O(N), where N is the size
  of the original_list.
  """

  # Compact the list in-place.
  new_list_size = 0
  for item in original_list:
    if func(item):
      original_list[new_list_size] = item
      new_list_size += 1

  # Remove trailing items from the list.
  tail_size = len(original_list) - new_list_size
  while tail_size:
    original_list.pop()
    tail_size -= 1


a = [1, 2, 3, 4, 5, 6, 7]

# Remove even numbers from a in-place.
filter_inplace(lambda x: x & 1, a)

# Prints [1, 3, 5, 7]
print a

편집:실제로,이 솔루션 https://stackoverflow.com/a/4639748/274937 우수한 광산 솔루션입니다.그것은 더 pythonic 고 빠르게 작동합니다.그래서,여기에 새로운 filter_inplace()구현:

def filter_inplace(func, original_list):
  """ Filters the original_list inplace.

  Removes elements from the original_list for which function returns False.

  Algrithm's computational complexity is O(N), where N is the size
  of the original_list.
  """
  original_list[:] = [item for item in original_list if func(item)]

필터 목록을 함축하는 확인을 위해 예를 들어,하지만 그들 부부의 문제는:

  • 그들은 복사본을 만들의 목록을 반환하고 새로운 중 하나는 것입니다 비효율적이 될 때 원래의 목록은 정말 큰
  • 그들은 정말이 될 수 있습니다 복잡할 때의 기준을 선택하는 항목에서(당신의 경우,이름[-5:]=='스미스')은 더 복잡하거나 여러 조건입니다.

원래의 솔루션은 실제로 더 효율적으로 아주 큰 나열하는 경우에도,우리 합의할 수 있는 그것의 추.하지만 경우에 당신을 걱정할 수 있는 여러 개 있는'존 스미스',그것에 의해 해결할 수 있습을 삭제하는 위치를 기반으로지에서 값:

names = ['Jones', 'Vai', 'Smith', 'Perez', 'Smith']

toremove = []
for pos, name in enumerate(names):
    if name[-5:] == 'Smith':
        toremove.append(pos)
for pos in sorted(toremove, reverse=True):
    del(names[pos])

print names

우리가 선택할 수 없습니다 솔루션을 고려하지 않고 크기의 목록은,하지만 큰 목록이 나는 것을 선호하는 2-을 전달하는 대신 솔루션의 필터링하거나 함축 목록

의 경우에는 설정합니다.

toRemove = set([])  
for item in mySet:  
    if item is unwelcome:  
        toRemove.add(item)  
mySets = mySet - toRemove 

여기에 나 filter_inplace 구현하는 데 사용할 수 있는 필터 목록에서 항목을 장소에,나는 내 자신이 독립적으로 찾기 전에 이 페이지로 이동합니다.그것은 동일한 알고리즘으로 무엇 PabloG 게시,그냥 보다 일반적인 사용할 수 있도록을 필터 목록을 장소에,그것은 또한 수에서 제거하는 기준으로 목록 comparisonFunc 는 경우 반대로 설정 True;정렬의 역 필터는 경우에 당신은 것입니다.

def filter_inplace(conditionFunc, list, reversed=False):
    index = 0
    while index < len(list):
        item = list[index]

        shouldRemove = not conditionFunc(item)
        if reversed: shouldRemove = not shouldRemove

        if shouldRemove:
            list.remove(item)
        else:
            index += 1

만,이것은 분명히 문제로 데이터 구조를 사용하고 있습니다.사용 hashtable 에 대한 예입니다.일부 구현을 지원하는 여러 항목을 키당,그래서 하나 pop 최신의 요소 또는 제거하 모니다.

그러나 이것은,그리고 당신이 무슨 솔루션을 찾을 수있는,우아함을 통해 서로 다른 데이터 구조,지 않는 알고리즘이 있습니다.어쩌면 당신은 더 잘 할 수 있다면 그것은 정렬하거나 무언가를하지만,반복 목록에 당신의 방법만 여기에.

편집: 중 하나가 깨닫는 그 요청의 효율성'...이러한 모든 제안된 방법만을 반복하는 목록은 동일한으로 그가 무엇을 권장합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top