질문
리스트 ["foo", "bar", "baz"]
와 리스트 내 항목 "bar"
가 주어졌을 때, 해당 항목의 인덱스 1
을 어떻게 얻을 수 있을까요?
답변
>>> ["foo", "bar", "baz"].index("bar")
1
내장된 .index()
메소드의 문서를 참조하십시오:
list.index(x[, start[, end]])
값이 x와 같은 첫 번째 항목의 0을 기준으로 한 리스트 내의 인덱스를 반환합니다. 해당 항목이 없으면
ValueError
가 발생합니다.선택적 인수 start와 end는 슬라이스 표기법과 같이 해석되며 리스트의 특정 하위 시퀀스에서 검색을 제한하는 데 사용됩니다. 반환된 인덱스는 시작 인수가 아닌 전체 시퀀스의 시작부터 계산됩니다.
주의 사항
리스트 길이에 대한 선형 시간 복잡성
index
호출은 일치하는 항목을 찾을 때까지 순서대로 리스트의 모든 요소를 확인합니다. 리스트가 길고 값이 시작 부근에 있을 것이 보장되지 않으면 이는 코드를 느리게 만들 수 있습니다.
이 문제는 다른 데이터 구조를 사용해야만 완전히 피할 수 있습니다. 그러나 요소가 리스트의 특정 부분에 있을 것으로 알려져 있다면, start
와 end
매개변수를 사용하여 검색 범위를 좁힐 수 있습니다.
예를 들어:
>>> import timeit
>>> timeit.timeit('l.index(999_999)', setup='l = list(range(0, 1_000_000))', number=1000)
9.356267921015387
>>> timeit.timeit('l.index(999_999, 999_990, 1_000_000)', setup='l = list(range(0, 1_000_000))', number=1000)
0.0004404920036904514
두 번째 호출은 1백만 개의 모든 요소를 검색하는 대신 10개의 요소만 검색하면 되므로 몇 가지 차이가 있습니다.
첫 번째 일치 항목의 인덱스만 반환됩니다.
index
호출은 일치하는 항목을 찾을 때까지 리스트를 순서대로 검색하고 그곳에서 멈춥니다. 값이 두 번 이상 나타날 수 있고 모든 인덱스가 필요한 경우, index
는 문제를 해결할 수 없습니다:
>>> [1, 1].index(1) # `1`의 인덱스가 발견되지 않습니다.
0
대신 리스트 컴프리헨션 또는 제너레이터 표현식을 사용하여 검색하고, enumerate
를 사용하여 인덱스를 가져와야 합니다::
>>> # 리스트 컴프리헨션은 인덱스 목록을 직접 제공합니다:
>>> [i for i, e in enumerate([1, 2, 1]) if e == 1]
[0, 2]
>>> # 제너레이터 컴프리헨션은 반복 가능한 객체를 제공합니다...
>>> g = (i for i, e in enumerate([1, 2, 1]) if e == 1)
>>> # `for` 루프에서 사용하거나 `next`로 수동으로 반복할 수 있습니다:
>>> next(g)
0
>>> next(g)
2
리스트 컴프리헨션 및 제너레이터 표현식 기술은 하나의 일치 항목만 있는 경우에도 작동하며, 더 일반적입니다.
일치하는 항목이 없으면 예외가 발생합니다.
위의 문서에서 언급한 대로, .index
를 사용하면 검색 대상 값이 리스트에 없으면 예외가 발생합니다:
>>> [1, 1].index(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: 2 is not in list
이것이 문제가 될 경우, item in my_list
를 사용하여 명시적으로 먼저 확인하거나 적절한 경우 try
/except
로 예외를 처리하십시오.
명시적 확인은 간단하고 읽기 쉬우나 두 번째로 목록을 반복해야 합니다. 이 선택에 대한 더 많은 지침은 파이썬의 EAFP 원칙을 참조하십시오.
댓글