python - 파이썬




Python에서 목록을 포함하는 항목의 색인 찾기 (18)

Python에서 목록을 포함하는 항목의 색인 찾기

목록 ["foo", "bar", "baz"] 및 목록 "bar" 의 항목에 대해 파이썬에서 인덱스 (1)를 얻는 가장 깨끗한 방법은 무엇입니까?

첫 번째 발생 색인을 반환하는 index 메소드가 있습니다.

>>> l = ["foo", "bar", "baz"]
>>> l.index('bar')
1

이 방법에는 몇 가지 문제가 있습니다.

  • 값이 목록에 없으면 ValueError
  • 두 개 이상의 값이 목록에 있으면 첫 번째 인덱스 만 가져옵니다.

값 없음

값이 누락 될 수 있으면 ValueError 를 catch해야합니다.

다음과 같이 재사용 가능한 정의를 사용하면됩니다.

def index(a_list, value):
    try:
        return a_list.index(value)
    except ValueError:
        return None

그리고 이것을 다음과 같이 사용하십시오 :

>>> print(index(l, 'quux'))
None
>>> print(index(l, 'bar'))
1

그리고 이것의 단점은 아마도 반환 값 is None인지 아닌지에 대한 검사를 할 것입니다.

result = index(a_list, value)
if result is not None:
    do_something(result)

목록에서 둘 이상의 값

더 많은 사건이 발생할 수 있다면 list.index 완전한 정보를 list.index :

>>> l.append('bar')
>>> l
['foo', 'bar', 'baz', 'bar']
>>> l.index('bar')              # nothing at index 3?
1

목록 이해력을 색인으로 열거 할 수 있습니다.

>>> [index for index, v in enumerate(l) if v == 'bar']
[1, 3]
>>> [index for index, v in enumerate(l) if v == 'boink']
[]

어커런스가없는 경우 결과의 부울 검사를 통해 확인할 수 있습니다. 결과를 반복하면 아무 것도하지 않습니다.

indexes = [index for index, v in enumerate(l) if v == 'boink']
for index in indexes:
    do_something(index)

팬더로 더 나은 데이터 munging

팬더가 있으면 Series 객체로 쉽게이 정보를 얻을 수 있습니다.

>>> import pandas as pd
>>> series = pd.Series(l)
>>> series
0    foo
1    bar
2    baz
3    bar
dtype: object

비교 검사는 일련의 불리언 값을 반환합니다.

>>> series == 'bar'
0    False
1     True
2    False
3     True
dtype: bool

일련의 부울을 일련 번호 표기법을 통해 시리즈에 전달하면 일치하는 멤버 만 얻을 수 있습니다.

>>> series[series == 'bar']
1    bar
3    bar
dtype: object

인덱스 만 원할 경우 index 속성은 일련의 정수를 반환합니다.

>>> series[series == 'bar'].index
Int64Index([1, 3], dtype='int64')

그리고 목록이나 튜플에 넣고 싶다면 생성자에게 전달하십시오.

>>> list(series[series == 'bar'].index)
[1, 3]

네, 열거 형과 함께리스트 독해력을 사용할 수도 있지만 제 생각에는 우아하지 않습니다. C로 작성된 내장 코드를 처리하는 대신 파이썬에서 평등을 테스트하고 있습니다.

>>> [i for i, value in enumerate(l) if value == 'bar']
[1, 3]

XY 문제 입니까?

XY 문제는 실제 문제가 아니라 시도한 해결책을 묻는 것입니다.

왜 목록에 요소가있는 색인이 필요하다고 생각하십니까?

당신이 이미 그 가치를 안다면, 왜 그것이 목록에 있는지 관심을 갖습니다.

그 값이 없다면, ValueError 잡는 것이 다소 장황하다. 나는 그것을 피하는 것을 선호한다.

어쨌든 나는 보통리스트를 반복하고 있으므로, 나는 흥미로운 정보를 가리키는 포인터를 열거하고, 열거로 인덱스를 얻는다 .

데이터를 잘못 작성했다면 판다를 사용해야 할 것입니다. 판다는 순수 파이썬 해결 방법보다 훨씬 우아한 도구를 가지고 있습니다.

나는 list.index 가 필요 list.index 것을 상기하지 않는다. 그러나 파이썬 표준 라이브러리를 살펴 보았고 몇 가지 훌륭한 용도가 있습니다.

GUI 및 텍스트 구문 분석을 위해 idlelib 많은 용도가 많이 있습니다.

keyword 모듈은이를 사용하여 모듈에서 주석 마커를 찾아서 메타 프로그래밍을 통해 키워드 목록을 자동으로 재생성합니다.

Lib / mailbox.py에서는 정렬 된 매핑처럼 사용하고있는 것 같습니다 :

key_list[key_list.index(old)] = new

del key_list[key_list.index(key)]

Lib / http / cookiejar.py에서 다음 달에 사용하는 것으로 보입니다.

mon = MONTHS_LOWER.index(mon.lower())+1

Lib / tarfile.py에서 distutils와 비슷하게 항목까지 슬라이스를 얻으려면 :

members = members[:members.index(tarinfo)]

Lib / pickletools.py의 경우 :

numtopop = before.index(markobject)

이러한 사용법은 공통적으로 보이는 것처럼 제한된 크기의 목록 ( list.index 의 O (n) 조회 시간 때문에 중요)에서 작동하는 것으로 보이며 주로 구문 분석에 사용됩니다 (예 : 게으른).

거기에는 유스 케이스가 있지만, 매우 드물다. 이 답변을 찾으려면 사용 사례에 해당 언어에서 제공되는 도구를 가장 직접적으로 사용하는지 스스로에게 자문 해보십시오.

목록 ["foo", "bar", "baz"] 및 목록 "bar" 의 항목에 대해 파이썬에서 색인 (1)을 얻으려면 어떻게해야합니까?


그리고 지금, 완전히 다른 무언가를 위해 ...

... 색인을 얻기 전에 항목의 존재를 확인하는 것과 같습니다. 이 접근법에 대한 좋은 점은 빈 목록 인 경우에도 함수는 항상 인덱스 목록을 반환한다는 것입니다. 문자열과도 잘 작동합니다.

def indices(l, val):
    """Always returns a list containing the indices of val in the_list"""
    retval = []
    last = 0
    while val in l[last:]:
            i = l[last:].index(val)
            retval.append(last + i)
            last += i + 1   
    return retval

l = ['bar','foo','bar','baz','bar','bar']
q = 'bar'
print indices(l,q)
print indices(l,'bat')
print indices('abcdaababb','a')

대화식 파이썬 창에 붙여 넣을 때 :

Python 2.7.6 (v2.7.6:3a1db0d2747e, Nov 10 2013, 00:42:54) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def indices(the_list, val):
...     """Always returns a list containing the indices of val in the_list"""
...     retval = []
...     last = 0
...     while val in the_list[last:]:
...             i = the_list[last:].index(val)
...             retval.append(last + i)
...             last += i + 1   
...     return retval
... 
>>> l = ['bar','foo','bar','baz','bar','bar']
>>> q = 'bar'
>>> print indices(l,q)
[0, 2, 4, 5]
>>> print indices(l,'bat')
[]
>>> print indices('abcdaababb','a')
[0, 4, 5, 7]
>>> 

최신 정보

머리말을들이는 파이썬 개발의 또 다른 해를 맞이하여 필자는 원래의 대답에 조금 당혹 스럽다. 그래서 레코드를 곧바로 설정하려면 분명히 위의 코드를 사용할 수있다. 그러나 같은 동작을 얻는 훨씬 더 관용적 인 방법은 enumerate () 함수와 함께 목록 이해를 사용하는 것입니다.

이 같은:

def indices(l, val):
    """Always returns a list containing the indices of val in the_list"""
    return [index for index, value in enumerate(l) if value == val]

l = ['bar','foo','bar','baz','bar','bar']
q = 'bar'
print indices(l,q)
print indices(l,'bat')
print indices('abcdaababb','a')

인터랙티브 파이썬 창에 붙여 넣으면 다음과 같이됩니다.

Python 2.7.14 |Anaconda, Inc.| (default, Dec  7 2017, 11:07:58) 
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def indices(l, val):
...     """Always returns a list containing the indices of val in the_list"""
...     return [index for index, value in enumerate(l) if value == val]
... 
>>> l = ['bar','foo','bar','baz','bar','bar']
>>> q = 'bar'
>>> print indices(l,q)
[0, 2, 4, 5]
>>> print indices(l,'bat')
[]
>>> print indices('abcdaababb','a')
[0, 4, 5, 7]
>>> 

그리고 지금,이 질문과 모든 답을 검토 한 결과, 이것은 이전의 대답 에서 제안한 것과 정확히 일치한다는 것을 습니다. 원래이 질문에 대답 할 때, 나는 그 대답을 보지 못했습니다. 이해하지 못했기 때문입니다. 좀 더 자세한 예가 이해를 돕기를 바랍니다.

위의 한 줄의 코드가 여전히 이해 가되지 않으면 Google의 'python list comprehension'을 사용하는 것이 좋습니다. 몇 분 정도 익숙해 지도록하십시오. Python을 사용하여 코드를 개발하는 것이 매우 기쁜 요소입니다.


목록에서 하나 이상의 (동일한) 항목의 모든 발생 및 위치 가져 오기

enumerate (alist)를 사용하면 요소 x가 사용자가 찾은 것과 동일 할 때 목록의 색인 인 첫 번째 요소 (n)를 저장할 수 있습니다.

>>> alist = ['foo', 'spam', 'egg', 'foo']
>>> foo_indexes = [n for n,x in enumerate(alist) if x=='foo']
>>> foo_indexes
[0, 3]
>>>

findindex 함수를 만들어 보자.

이 함수는 항목과 목록을 인수로 사용하고 이전에 본 것처럼 목록의 항목 위치를 반환합니다.

def indexlist(item2find, list_or_string):
  "Returns all indexes of an item in a list or a string"
  return [n for n,item in enumerate(list_or_string) if item==item2find]

print(indexlist("1", "010101010"))

산출

[1, 3, 5, 7]

단순한

for n, i in enumerate([1, 2, 3, 4, 1]):
    if i == 1:
        print(n)

산출:

0
4

@TerryA에 표시된 바와 같이, 하나의 색인을 찾는 방법에 대한 많은 답이 있습니다.

more_itertools 는 반복 가능한 범위 내에서 여러 색인을 찾을 있는 도구가 포함 된 타사 라이브러리입니다.

주어진

import more_itertools as mit


iterable = ["foo", "bar", "baz", "ham", "foo", "bar", "baz"]

암호

여러 관측의 색인을 찾으십시오.

list(mit.locate(iterable, lambda x: x == "bar"))
# [1, 5]

여러 항목 테스트 :

list(mit.locate(iterable, lambda x: x in {"bar", "ham"}))
# [1, 3, 5]

more_itertools.locate 와 함께 더 많은 옵션을 참조하십시오. more_itertools 를 통해 more_itertools .


간단히 갈 수 있습니다.

a = [['hand', 'head'], ['phone', 'wallet'], ['lost', 'stock']]
b = ['phone', 'lost']

res = [[x[0] for x in a].index(y) for y in b]

검색중인 요소가 목록에 있는지 확인하기위한 조건을 설정해야합니다.

if 'your_element' in mylist:
    print mylist.index('your_element')
else:
    print None

다른 옵션

>>> a = ['red', 'blue', 'green', 'red']
>>> b = 'red'
>>> offset = 0;
>>> indices = list()
>>> for i in range(a.count(b)):
...     indices.append(a.index(b,offset))
...     offset = indices[-1]+1
... 
>>> indices
[0, 3]
>>> 

대부분의 답변 은 단일 색인 을 찾는 방법을 설명하지만 항목이 목록에 여러 번있는 경우 여러 색인을 반환하지 않습니다. enumerate() :

for i, j in enumerate(['foo', 'bar', 'baz']):
    if j == 'bar':
        print(i)

index() 함수는 첫 번째 항목 만 반환하고 enumerate() 는 모든 항목을 반환합니다.

명부 작성으로 :

[i for i, j in enumerate(['foo', 'bar', 'baz']) if j == 'bar']

itertools.count() 사용하는 또 다른 작은 해결책이 있습니다 (이는 열거 형과 거의 같은 방식입니다).

from itertools import izip as zip, count # izip for maximum efficiency
[i for i, j in zip(count(), ['foo', 'bar', 'baz']) if j == 'bar']

이것은 enumerate() 사용하는 것보다 큰 목록에 더 효율적입니다.

$ python -m timeit -s "from itertools import izip as zip, count" "[i for i, j in zip(count(), ['foo', 'bar', 'baz']*500) if j == 'bar']"
10000 loops, best of 3: 174 usec per loop
$ python -m timeit "[i for i, j in enumerate(['foo', 'bar', 'baz']*500) if j == 'bar']"
10000 loops, best of 3: 196 usec per loop

모든 색인이 필요하면 NumPy 를 사용할 수 있습니다.

import numpy as np

array = [1, 2, 1, 3, 4, 5, 1]
item = 1
np_array = np.array(array)
item_index = np.where(np_array==item)
print item_index
# Out: (array([0, 2, 6], dtype=int64),)

명확하고 읽기 쉬운 솔루션입니다.


목록에 색인을 확인해야하는 반복 항목이없는 경우 두 가지 가능성이 있습니다.

 eg: li=[10,20,30] # here need to get index of 20 means
     li.index(20) # will work properly because 20 is not repeated

그것의 반복되는 경우에 당신에게 첫번째 색인 만 줄 것이다

항목이있는 모든 색인을 가져와야하는 경우

eg: li=[10,20,30,20,40, 50, 10] # here need to get index of 20 means its have 2 index (1,3) 

당신이 그것을 할 필요가 있다는 것을 얻으려면

 li=[10,20,30,20,40, 50, 10]
 [i for i, e in enumerate(li) if e == 20]

그러면 [1,3]과 같은 o / p 인덱스 목록을 얻을 수 있습니다.


여기에 제안 된 모든 기능은 고유 한 언어 동작을 재현하지만 현재 진행중인 작업을 모호하게 만듭니다.

[i for i in range(len(mylist)) if mylist[i]==myterm]  # get the indices

[each for each in mylist if each==myterm]             # get the items

mylist.index(myterm) if myterm in mylist else None    # get the first index and fail quietly

왜 언어가 당신이 원하는 것을 할 수있는 방법을 제공한다면 예외 처리 기능을 쓰는가?


요소가 목록에 없으면 문제가 발생합니다. 이 함수는이 문제를 처리합니다.

# if element is found it returns index of element else returns None

def find_element_in_list(element, list_element):
    try:
        index_element = list_element.index(element)
        return index_element
    except ValueError:
        return None

이것에 대한 더 기능적인 대답이 있습니다.

list(filter(lambda x: x[1]=="bar",enumerate(["foo", "bar", "baz", "bar", "baz", "bar", "a", "b", "c"])))

보다 일반적인 형식 :

def get_index_of(lst, element):
    return list(map(lambda x: x[0],\
       (list(filter(lambda x: x[1]==element, enumerate(lst))))))

파이썬리스트는 0부터 시작하므로, 다음과 같이 zip 내장 함수를 사용할 수 있습니다 :

>>> [i for i,j in zip(range(len(haystack)), haystack) if j == 'needle' ]

여기서 "haystack"은 문제의 목록이고 "needle"은 찾을 항목입니다.

(참고 : 여기서 i를 사용하여 인덱스를 얻는 것을 반복하지만, 항목으로 집중할 필요가 있다면 j로 전환 할 수 있습니다.)


항목을 찾지 못하면 Python index() 메서드가 오류를 발생시킵니다.

따라서 대신 JavaScript의 indexOf() 함수와 유사하게 만들 수 있습니다.이 함수는 항목을 찾을 수없는 경우 -1 을 반환합니다.

    try:
        index = array.index('search_keyword')
    except ValueError:
        index = -1

zip 기능이있는 모든 색인 :

get_indexes = lambda x, xs: [i for (y, i) in zip(xs, range(len(xs))) if x == y]

print get_indexes(2, [1, 2, 3, 4, 5, 6, 3, 2, 3, 2])
print get_indexes('f', 'xsfhhttytffsafweef')

>>> ["foo", "bar", "baz"].index("bar")
1

참조 : 데이터 구조> 목록에 대한 추가 정보

주의 사항

요청한대로 질문에 대답하는 가장 쉬운 방법 일 수도 있지만 indexlist API의 약한 구성 요소이므로 분노로 사용한 마지막 시간을 기억할 수 없습니다. 이 답변은 많이 언급 되었기 때문에보다 완벽하게 작성되어야한다는 의견이 나에게 지적되었습니다. list.index 에 대한 몇 가지주의 사항이 따릅니다. 처음에는 문서화 문자열을 살펴볼 가치가 있습니다.

>>> print(list.index.__doc__)
L.index(value, [start, [stop]]) -> integer -- return first index of value.
Raises ValueError if the value is not present.

선형 길이 - 목록 길이의 복잡성

index 호출은 일치하는 항목을 찾을 때까지 목록의 모든 요소를 ​​순서대로 검사합니다. 목록이 길고 목록의 어디에서 발생하는지 대략 알지 못하는 경우이 검색이 병목 현상이 될 수 있습니다. 이 경우 다른 데이터 구조를 고려해야합니다. 대략 일치하는 부분을 알면 index 에 힌트를 줄 수 있습니다. 예를 들어,이 스 니펫에서 l.index(999_999, 999_990, 1_000_000) 는 직선 l.index(999_999) 보다 약 5 배 빠릅니다. 왜냐하면 전자는 10 개의 항목을 검색해야하기 때문에 후자는 백만을 검색합니다.

>>> 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

오직 첫 번째 일치 인덱스를 인수로 반환합니다.

index 호출은 일치하는 항목을 찾을 때까지 순서대로 목록을 검색하고 거기에서 중지합니다. 더 많은 일치 지수가 필요할 것으로 예상되는 경우 목록 이해 또는 생성자 표현식을 사용해야합니다.

>>> [1, 1].index(1)
0
>>> [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)
>>> next(g)
0
>>> next(g)
2

한 번 index 을 사용했던 대부분의 장소에서, 나는 더 일반화 될 수 있기 때문에 이제는 목록 이해 또는 생성자 표현을 사용합니다. 따라서 index 을 얻으 려한다면이 우수한 파이썬 기능을 살펴보십시오.

요소가리스트에 존재하지 않는 경우에 슬로우한다

항목이 없으면 index 호출하면 ValueError 발생합니다.

>>> [1, 1].index(2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: 2 is not in list

해당 항목이 목록에 없을 경우,

  1. item in my_list 있는 item in my_list 먼저 확인 (깨끗하고 읽기 쉬운 방법)하거나
  2. ValueError 를 포착하는 try/except 블록에서 index 호출을 감싸십시오. (적어도 검색 할 목록이 길면 항목이 대개 더 빠를 때 더 빠릅니다.)

a = ["foo","bar","baz",'bar','any','much']

indexes = [index for index in range(len(a)) if a[index] == 'bar']




list