파이썬 목록 이해 내에서 계산 된 값을 효율적으로 필터링하려면 어떻게해야합니까?

StackOverflow https://stackoverflow.com/questions/130262

  •  02-07-2019
  •  | 
  •  

문제

Python List Comprehension Syntax를 사용하면 이해력 내에서 값을 쉽게 필터링 할 수 있습니다. 예를 들어:

result = [x**2 for x in mylist if type(x) is int]

MyList에서 정수 제곱 목록을 반환합니다. 그러나 테스트에 일부 (비용이 많이 드는) 계산이 포함되어 결과를 필터링하려면 어떻게해야합니까? 하나의 옵션은 다음과 같습니다.

result = [expensive(x) for x in mylist if expensive(x)]

이로 인해 비 "false"비싼 (x) 값 목록이 발생하지만 각 x마다 비싸다 ()는 두 번 호출됩니다. X 당 한 번만 비싸지만이 테스트를 수행 할 수있는 이해력 구문이 있습니까?

도움이 되었습니까?

해결책

계산이 이미 기능으로 잘 번들되어 있다면 어떻게 filter 그리고 map?

result = filter (None, map (expensive, mylist))

당신이 사용할 수있는 itertools.imap 목록이 매우 큰 경우.

다른 팁

잠시 생각 후에 내 자신의 대답을 생각해 냈습니다. 중첩 된 이해로 수행 할 수 있습니다.

result = [y for y in (expensive(x) for x in mylist) if y]

중첩 된 이해력이 약간만 읽을 수 있다고 생각하지만 효과가 있다고 생각합니다.

가장 분명한 (그리고 가장 읽기 쉬운 것) 대답은 목록 이해력이나 발전기 표현식을 사용하지 않고 오히려 실제 생성기를 사용하는 것입니다.

def gen_expensive(mylist):
    for item in mylist:
        result = expensive(item)
        if result:
            yield result

더 많은 수평 공간이 필요하지만 한 눈에 무엇을하는지 알기가 훨씬 쉽고 자신을 반복하지 않습니다.

result = [x for x in map(expensive,mylist) if x]

Map ()는 MyList에있는 각 객체의 값 목록을 비싼 ()로 반환합니다. 그런 다음 이해하고 불필요한 값을 폐기 할 수 있습니다.

이것은 중첩 된 이해력과 다소 더 빠르지 않지만 더 빠릅니다 (Python 통역사가 상당히 쉽게 최적화 할 수 있기 때문에).

이것이 바로 발전기가 처리하기에 적합한 것입니다.

result = (expensive(x) for x in mylist)
result = (do_something(x) for x in result if some_condition(x))
...
result = [x for x in result if x]  # finally, a list
  1. 이것은 파이프 라인의 각 단계에서 일어나는 일을 완전히 명확하게합니다.
  2. 암시 적에 대한 명시 적
  3. 최종 단계까지 모든 곳에서 발전기를 사용하므로 큰 중간 목록이 없습니다.

CF : David Beazley의 '시스템 프로그래머를위한 발전기 트릭'

당신은 항상 할 수 있습니다 메모에 그만큼 expensive() 두 번째로 부르는 기능을하는 기능은 단지 계산 된 값을 조회하는 것입니다. x.

다음은 데코레이터로 메모 라이즈의 많은 구현 중 하나입니다..

비싸지 않은 (x)를 메모 할 수 있습니다 (그리고 비싸기 (x)를 자주 호출하는 경우 어떤 방식 으로든 메모를 메모해야 할 것입니다.이 페이지는 Python에 대한 메모 라이즈를 구현합니다.

http://code.activestate.com/recipes/52201/

이것은 비싸다 (x)가 실행될 수 있다는 추가 이점이 있습니다. 더 적은 중복 항목은 이전 실행에서 메모를 사용하기 때문에 n 번보다.

이것은 비싸다고 가정합니다 (x)는 진정한 기능이며 변할 수있는 외부 상태에 의존하지 않습니다. 비싸면 (x)가 외부 상태에 의존하고 해당 상태가 변경되는시기를 감지하거나 알고 있습니다 습관 목록 이해 중에 변경하면 이해하기 전에 메모를 재설정 할 수 있습니다.

나는 다음을 선호 할 것이다 :

itertools.ifilter(bool, (expensive(x) for x in mylist))

이것은 다음과 같은 이점이 있습니다.

a의 평범한 오래된 사용이 있습니다 for 목록에 추가하려면 루프 :

result = []
for x in mylist:
    expense = expensive(x)
    if expense:
        result.append(expense)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top