x보다 큰 첫 번째 Python 목록 색인?


81

x보다 큰 목록에서 첫 번째 인덱스를 찾는 가장 Pythonic 방법은 무엇입니까?

예를 들어

list = [0.5, 0.3, 0.9, 0.8]

함수

f(list, 0.7)

돌아올 것이다

2.

57
... 변수 이름으로 '목록'을 사용하지 않는
mshsayem

11
당신은 "파이썬"을 의미합니다. urbandictionary.com/define.php?term=Pythonesque 에 따르면 , "pythonesque"는 "초현실적, 터무니없는"을 의미하며 그게 당신이 찾고있는 것 같지 않습니다. : P
Roberto Bonvallet

1
질문은 모호합니다. 답변입니다 2때문에 0.9 > 0.7나 때문에는 0.8 > 0.7? 즉, 순차적으로 검색합니까 아니면 값이 증가하는 순서대로 검색합니까?
Sergey Orshanskiy 2015 년


나는 새로운 질문이 더 일반적이기 때문에이 질문을 반대로하는 대신 중복으로 닫기로 투표했습니다.
Cristian Ciupitu

답변:


118
next(x[0] for x in enumerate(L) if x[1] > 0.7)

29
+1 : 매직 넘버를 피하고 싶지만 : next (idx for idx, value in enumerate (L) if value> 0.7)
truppo

38
단순함을 위해 +1하고 next()가독성 을 위해 다음과 같습니다.next(i for i,v in enumerate(L) if v > 0.7)
Will Hardy

14
보기에는 좋지만 결과가없는 경우 혼란스러운 StopIteration이 발생합니다.
Virgil Dupras 2010

3
@Wim :하지만 전체 시퀀스를 평가하기 위해 회귀합니다. itertools.chain()이와 같은 목록을 추가하는 대신 사용하십시오 .
Ignacio Vazquez-Abrams

3
@Wim 여기에 chain ()이 필요하지 않습니다. next ()는 두 번째 인수를 허용합니다.next((i for i, x in enumerate(L) if x > value), -1)
jfs

35

목록이 정렬되면 bisect.bisect_left(alist, value)큰 목록의 경우보다 빠릅니다 next(i for i, x in enumerate(alist) if x >= value).


좋은 대답-작은 4 요소 정렬 목록을 사용하여 확실히 5 ~ 6 배 빠르지 만 (오류가 발생했는지 확실하지 않음) 10000 요소 numpy 배열의 긴 목록과 함께 timeit을 사용하여 시간을 측정하면 위의 목록 이해력 답변보다 약 두 배 느리다는 것을 알았습니다.
Adrian Tompkins

1
@AdrianTompkins : 벤치 마크에 문제가 있습니다. bisect_left는 O (log n)이고 listcomp는 O (n)입니다. 즉, 더 클수록 측면 n에서 더 많은 이점이 bisect_left()있습니다. 나는의 인덱스를 찾기 위해 노력했습니다 500_000range(10**6)사용 bisect_left()> 3.75 마이크로와 함께 genexpr를 사용하여 - next()[> 51.0 밀리 초 - 10_000느린 같은 예상 시간].
jfs

16
filter(lambda x: x>.7, seq)[0]

4
-1 : 기술적으로 정확하지만 목록 이해도가 더 읽기 쉽고 성능이 더 뛰어난 필터를 사용하지 마십시오
truppo

filter (lambda x : x [1]> .7, enumerate (seq)) [0] [0]-단순 선형 검색
lowtech

4
파이썬 3의 @truppo 필터는 생성기를 반환하므로 목록 이해력보다 나쁘지 않아야합니까? 또한 열거 솔루션보다이 방법이 더 읽기 쉽습니다.
BubuIIC 2013

이것에 대해 좋지 않은 점은 seq에 .7보다 큰 항목이 없으면 예외 처리에 들어간다는 것입니다.
Brian C.

솔루션이 기술적으로 잘못되었습니다. 질문 작성자 는 목록에서 요소의 색인 을 찾는 방법을 물었습니다 . 그러나이 솔루션은 대신 레코드를 반환합니다. Python 3.8에서 Eventmore는 bisect_left()(가장 빠름) 느리고 enumerate().
Sergey Nevmerzhitsky

16
>>> alist= [0.5, 0.3, 0.9, 0.8]
>>> [ n for n,i in enumerate(alist) if i>0.7 ][0]
2

2
'x'가 목록의 다른 값보다 크면 실패합니다
mshsayem

2
@mshsayem :이 경우 문제가 잘못 정의되었습니다. 실패는 옳은 일일 수 있습니다.
S.Lott

@ S.Loot : 좋은 지적입니다. 목록에없는 경우 실패하면이를 변수에 할당 할 때 이해할 수있는 오류가 발생 IndexError: list index out of range합니다.. index = next[ n for n,i in enumerate(alist) if i>0.7 ]오류를 사용하면 NameError: name 'index' is not defined. next약간 더 빠릅니다. 타이밍 차이는 60,000 개의 숫자에 대해 12.7ns 대 11.9ns입니다.
Leo

11
for index, elem in enumerate(elements):
    if elem > reference:
        return index
raise ValueError("Nothing Found")


3

1) NUMPY ARGWHERE, 일반 목록

numpy를 사용하는 것이 좋으면 일반 목록 (정렬 또는 정렬되지 않음)에서 다음이 작동합니다.

numpy.argwhere(np.array(searchlist)>x)[0]

또는 목록으로 답변이 필요한 경우 :

numpy.argwhere(np.array(searchlist)>x).tolist()[0]

또는 정수 인덱스로 답이 필요한 경우 :

numpy.argwhere(np.array(searchlist)>x).tolist()[0][0]

2) NUMPY SEARCHSORTED, 정렬 된 목록 (목록 검색에 매우 효율적)

그러나 검색 목록이 정렬되어 있으면 np.searchsorted 함수를 사용하는 것이 훨씬 더 깔끔하고 좋습니다 .

numpy.searchsorted(searchlist,x)

이 함수를 사용할 때 좋은 점은 단일 값 x를 검색 할뿐만 아니라 x도 목록이 될 수 있다는 것입니다. 즉, 검색된 값 목록 [x1, x2, x3 .. xn에 대한 색인 목록을 반환 할 수도 있습니다. ], ( 이 경우 목록 이해력에 비해 매우 효율적입니다 ).


2

내 목록이 매우 길 때 비슷한 문제가 발생했습니다. 이해력 또는 필터 기반 솔루션은 전체 목록을 통과합니다. itertools.takewhile은 조건이 처음 거짓이되면 루프를 중단합니다.

from itertools import takewhile

def f(l, b): return len([x for x in takewhile(lambda x: x[1] <= b, enumerate(l))])

l = [0.5, 0.3, 0.9, 0.8]
f(l, 0.7)

1
왜 def f (l, b) : return len (list (takewhile (lambda x : x [1] <= b, enumerate (l))))을 쓰지 않습니까?
Avo Asatryan

2

이미 많은 답이 있다는 것을 알고 있지만 가끔 비단뱀이라는 단어가 '한 줄'로 번역되는 느낌이 듭니다.

더 나은 정의 가이 답변에 더 가깝다고 생각할 때 :

"Python 언어의 기능을 활용하여 명확하고 간결하며 유지 관리 할 수있는 코드를 생성합니다."

위의 답변 중 일부는 간결하지만 명확하지 않으며 초보자 프로그래머가 이해하는 데 시간이 걸리므로 많은 기술 수준으로 구성된 팀에 대해 매우 유지 관리 할 수 ​​없습니다.

l = [0.5, 0.3, 0.9, 0.8]

def f(l, x):
    for i in l:
        if i >x: break
    return l.index(i)


f(l,.7)

또는

l = [0.5, 0.3, 0.9, 0.8]

def f(l, x):
    for i in l:
        if i >x: return l.index(i)



f(l,.7)

위의 내용은 초보자가 쉽게 이해할 수 있으며 베테랑 파이썬 프로그래머가 받아 들일만큼 간결하다고 생각합니다.

멍청한 코드를 작성 하는 것이 긍정적 이라고 생각 합니다.


1
>>> f=lambda seq, m: [ii for ii in xrange(0, len(seq)) if seq[ii] > m][0]
>>> f([.5, .3, .9, .8], 0.7)
2

꽤 매끄러운 것 같습니다. 그러나 이론적으로 전체 목록을 순회 한 다음 첫 번째 결과 (x보다 큼)를 반환합니다. 맞습니까? 첫 번째 결과를 찾은 후 곧바로 멈추는 것을 만들 수있는 방법이 있습니까?
c00kiemonster 2010

전체 목록을 순회하는 데 무엇이 문제입니까? 0.7보다 큰 첫 번째 값이 목록의 끝 근처에 있으면 차이가 없습니다.
ghostdog74 2010

3
진실. 그러나이 특별한 경우에 목록은 내가 ... 즉시 일치하는 항목이 발견으로 가로 지르는 종료를 선호하는 것, 그래서 꽤 긴의 기능을 사용하고자하는
c00kiemonster

길든 아니든, 첫 번째 값이 목록의 마지막 두 번째 항목이면 전체 목록을 탐색해야합니다.
ghostdog74 2010

4
@ ghostdog74 : 예,하지만 이것이 모든 경우가 최악의 경우가되기를 바라는 이유는 아닙니다.
UncleBens 2010


-1

이걸로 해봐:

def Renumerate(l):
    return [(len(l) - x, y) for x,y in enumerate(l)]

예제 코드 :

Renumerate(range(10))

산출:

(10, 0)
(9, 1)
(8, 2)
(7, 3)
(6, 4)
(5, 5)
(4, 6)
(3, 7)
(2, 8)
(1, 9)

1
질문은 " 목록에서 x보다 큰 첫 번째 색인을 찾는 것 "이었습니다.
Gino Mempin 19
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.