2011-12-16 2 views
110

어리석은 질문 : 저는 술어와 일치하는 목록에서 첫 번째 요소를 찾는 관용적 인 방법을 원합니다. 나는 그것을 변경에 대한 생각했습니다술어와 일치하는 시퀀스의 첫 번째 요소를 찾습니다.

[x for x in seq if predicate(x)][0] 

:

현재 코드는 아주 못생긴

from itertools import dropwhile 
dropwhile(lambda x: not predicate(x), seq).next() 

하지만이 ... 더 우아한 뭔가 있어야하며 경우에 좋은 것 일치하는 것이 없으면 예외를 발생시키지 않고 None 값을 리턴합니다.

는 난 그냥 같은 함수 정의 할 수 있습니다 알고

def get_first(predicate, seq): 
    for i in seq: 
     if predicate(i): return i 
    return None 

을하지만, 그래서 아마 그들은 이미이 있음을 통지하지 않습니다 유틸리티 같은 기능 (그리고 사람들과 코드를 작성 시작하는 것은 매우 맛입니다 그들은 이미 동일한 기능을 제공하는 내장 기능이 있다면 시간이 지남에 따라 반복되는 경향이 있습니다. 존재하지 않는 경우는

+1

이것은 바보 같은 질문이 아니며 @ j-f-sebastian : 이것은 중복되지 않습니다. 이 질문은 특히 하나의 객체를 반환하고 예외를 throw하는 대신 'None'을 반환하는 것에 관한 것입니다. 또한 우아함에 관한 것입니다. 다른 질문은 n00b 질문의 더 많은 것 및 적어도이 아주 명확하게 아닙니다이 것에, 사문하지 않는다. –

+1

"[python sequence find function] (https://stackoverflow.com/questions/6039425/python-sequence-find-function)"보다 나중에 질문하는 것 외에이 질문에는 ** 더 나은 제목 **이 있습니다. – Wolf

답변

159

next(x for x in seq if predicate(x))

그것은 StopIteration를 발생시킵니다.

next(ifilter(predicate, seq), None)

반환 None을 그러한 요소가 존재하지 않는 경우.

+12

또는 예외를 발생시키는 대신에 사용되는 두 번째 "기본"인수를 '다음'에 제공 할 수 있습니다. –

+2

@fortran : ['next()'] (http://docs.python.org/library/functions.html#next)는 Python 2.6부터 사용할 수 있습니다. [What 's New page] (http : // docs. python.org/whatsnew/2.7.html) 새로운 기능을 신속하게 익히십시오. – jfs

+1

저는 파이썬 초보자이며 문서를 읽고 ifilter는 "yield"메서드를 사용합니다. 나는 이것이 술어가 느리게 평가된다는 것을 의미한다고 가정합니다. 즉, 우리는 전체 목록을 통해 술어를 실행하지 않습니다. 왜냐하면 저는 약간 비싸고 술어가있는 항목까지만 반복하기를 원하기 때문입니다. –

68

당신은 기본 값으로 발전기 표현을 사용하고 next을 수 : 비록

next((x for x in seq if predicate(x)), None) 

을이 한 줄 당신은> = 2.6 Python을 사용해야합니다.

이 인기있는 기사에서는이 문제에 대해 자세히 설명합니다. Cleanest Python find-in-list function?.

3

질문에서 제안한 두 가지 해결책에 문제가 있다고 생각하지 않습니다. 내 자신의 코드에서

, 나는이 생각처럼 구현하는 것이 :

(x for x in seq if predicate(x)).next() 

()와 구문은 한 번에 [] 모든 목록을 생성하는 것보다 효율적이다 발전기를 만듭니다.

+0

그리고 iterator가 끝나지 않거나 그 요소를 만들기가 어렵다면'[]'를 사용하면 문제가 발생할 수 있습니다. – glglgl

+5

''generator '객체에는 없습니다. 애트리뷰트 '는 파이썬 3에서'next '라는 속성을 사용합니다. – jfs

+0

@glglgl - 첫 번째 포인트 (끝나지 않음)에 대해서는 인수가 유한 순서 임에 분명합니다. 두 번째는 다시 말하자면, 제공된 인자가 시퀀스이므로,이 함수가 호출 될 때까지 객체는 이미 생성되고 저장되어 있어야합니다 .... 아니면 뭔가 빠졌습니까? – mac

1

J.F. Sebastian의 대답은 가장 우아하지만 fortran이 지적한 것처럼 Python 2.6이 필요합니다.

파이썬 버전 < 2.당신이 그것을 할 수있는 모든 아직도 당신이 (목록은 StopIteration을 처리) 목록 나중에 필요한 경우 또는

from itertools import repeat,ifilter,chain 
chain(ifilter(predicate,seq),repeat(None)).next() 

, 아니면 그냥 처음보다 더 필요하지만, 6, 여기에 내가 가지고 올 수있는 최선의 방법 islice :

from itertools import islice,ifilter 
list(islice(ifilter(predicate,seq),1)) 

UPDATE :

: 필터/IFilter를 사용하지 : 나는 개인적으로 StopIteration을 잡는다 및 None을 돌려 첫 번째 (라는 미리 정의 된 함수)를 사용하고 있지만 , 여기에 위의 예를 통해 가능한 개선이다
from itertools import islice,chain 
chain((x for x in seq if predicate(x)),repeat(None)).next() 
+8

Yikes! 결론적으로, "if"가 포함 된 간단한 "for"루프를 작성하면됩니다. –

관련 문제