Поиск индекса элемента, заданного списком, содержащим его в Python

список ["foo", "bar", "baz"] и пункт в списке "bar", Как получить его индекс (1) в Python?

27 ответов


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

ссылки: структуры данных > Подробнее о списках

предостережения следуйте

обратите внимание, что хотя это, пожалуй, проще всего ответить на вопрос как просил, index является довольно слабым компонентом list API, и я не могу вспомнить, когда в последний раз я использовал его в гневе. В комментариях мне было указано, что, поскольку этот ответ сильно ссылается, он должен быть более полным. Некоторые предостережения о list.index следовать. Вероятно, стоит сначала взглянуть на docstring для него:

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

линейное время-сложность в длине списка

An index вызов проверяет каждый элемент списка по порядку, пока не найдет совпадение. Если ваш список будет длинный, и вы не знаете примерно, где в списке это происходит, этот поиск может стать узким местом. В этом случае следует рассмотреть другую структуру данных. Обратите внимание, что если вы примерно знаете, где найти матч, вы можете дай!--5--> подсказку. Например, в этом фрагменте l.index(999_999, 999_990, 1_000_000) примерно на пять порядков быстрее, чем прямой l.index(999_999), потому что первый должен искать только 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, взгляните на эти отличные функции python.

бросает, если элемент отсутствует в списке

вызов 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 (чистый, четкий подход), или
  2. оберните index вызов в try/except блок, который ловит ValueError (вероятно, быстрее, по крайней мере, когда Список для поиска длинный, и элемент обычно присутствует.)

одна вещь, которая действительно полезна в изучении Python, - это использование интерактивной функции справки:

>>> help(["foo", "bar", "baz"])
Help on list object:

class list(object)
 ...

 |
 |  index(...)
 |      L.index(value, [start, [stop]]) -> integer -- return first index of value
 |

что часто приведет вас к методу, который вы ищете.


большинство ответов объясняют, как найти единый индекс, но их методы не возвращают несколько индексов, если элемент находится в списке несколько раз. Использовать 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() (который в значительной степени тот же подход, что и enumerate):

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

чтобы получить все индексы:

 indexes = [i for i,x in enumerate(xs) if x == 'foo']

index() возвращает первый индекс стоимости!

/ index(...)
/ L. index (value, [start, [stop]]) - > integer -- возвращает первый индекс значения

def all_indices(value, qlist):
    indices = []
    idx = -1
    while True:
        try:
            idx = qlist.index(value, idx+1)
            indices.append(idx)
        except ValueError:
            break
    return indices

all_indices("foo", ["foo","bar","baz","foo"])

проблема возникнет, если элемент отсутствует в списке. Эта функция обрабатывает проблему:

# 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

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

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

вы должны установить условие, чтобы проверить, находится ли элемент, который вы ищете, в списке

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

все предлагаемые здесь функции воспроизводят присущее поведение языка, но затемняют то, что происходит.

[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

зачем писать функцию с обработкой исключений, если язык предоставляет методы для выполнения того, что вы хотите?


Если вы хотите все индексы, то вы можете использовать включает в себя:

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

Это ясное, читаемое решение.


Поиск индекса элемента, заданного списком, содержащим его в Python

список ["foo", "bar", "baz"] и пункт в списке "bar", что самый чистый способ получить его индекс (1) в Python?

ну, конечно, есть метод index, который возвращает индекс первого вхождения:

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

есть несколько проблем с этим методом:

  • если значение отсутствует в списке, вы получите ValueError
  • если в списке больше одного значения, вы получаете индекс только для первого

нет значений

если значение может отсутствовать, вам нужно поймать ValueError.

вы можете сделать это с помощью многоразового определения, как это:

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 или is not нет:

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

более одного значения в списке

если бы вы могли иметь больше случаев, вы будете не получите полную информацию с 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 с пандами

если у вас есть панды, вы можете легко получить эту информацию с объекта серия:

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

Да, вы можете использовать понимание списка с перечислением тоже, но это не так элегантно, на мой взгляд - вы делаете тесты на равенство в Python, вместо того, чтобы позволить встроенному коду, написанному на C, обрабатывать его:

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

это проблема по XY?

проблема XY спрашивает о вашем попытанном решении, а не о вашем фактическом проблема.

почему вы думаете, что вам нужен индекс, заданный элементом в списке?

если вы уже знаете значение, почему вас волнует, где оно находится в списке?

если значение не существует, ловя ValueError довольно многословно - и я предпочитаю избегать этого.

я обычно перебираю список в любом случае, поэтому я обычно держу указатель на любую интересную информацию, получая


все индексы с 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')

просто вы можете пойти с

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

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

другой вариант

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

вариант ответа от FMc и user7177 даст дикт, который может вернуть все индексы для любой записи:

>>> a = ['foo','bar','baz','bar','any', 'foo', 'much']
>>> l = dict(zip(set(a), map(lambda y: [i for i,z in enumerate(a) if z is y ], set(a))))
>>> l['foo']
[0, 5]
>>> l ['much']
[6]
>>> l
{'baz': [2], 'foo': [0, 5], 'bar': [1, 3], 'any': [4], 'much': [6]}
>>> 

вы также можете использовать это как одну строку, чтобы получить все индексы для одной записи. Нет никаких гарантий эффективности, хотя я использовал set(a), чтобы уменьшить количество раз, когда вызывается лямбда.


а теперь, для чего-то совершенно другого...

... например, подтверждение существования элемента перед получением индекса. Хорошая вещь об этом подходе является функция всегда возвращает список индексов, даже если это пустой список. Он также работает со строками.

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:

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

обновление

после еще одного года разработки heads-down python, я немного смущен по моему первоначальному ответу, чтобы установить запись прямо, можно, конечно, использовать приведенный выше код; однако много более идиоматичным способом получить такое же поведение было бы использовать понимание списка вместе с функцией 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 дает:

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

и теперь, после рассмотрения этого вопроса и всех ответов, я понимаю, что это именно то, что FMc в своем ранее ответа. В то время, когда я первоначально ответил на этот вопрос, я даже не посмотреть этот ответ, потому что я не понимаю. Я надеюсь, что мой несколько более подробный пример поможет понять.

если одна строка кода выше еще не имеет смысл для вас, я настоятельно рекомендую Вам Google "python list понимание" и занять несколько минут, чтобы ознакомиться. Это всего лишь одна из многих мощных функций, которые делают его радость использовать Python для разработки кода.


получение всех вхождений и положение одного или нескольких (идентичных) элементов в списке

С enumerate (alist) вы можете сохранить первый элемент (n), который является индексом списка, когда элемент x равен тому, что вы ищете.

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

это решение не так мощно, как другие, но если вы новичок и знаете только о forпетли по-прежнему можно найти первый индекс элемента, избегая ValueError:

def find_element(p,t):
    i = 0
    for e in p:
        if e == t:
            return i
        else:
            i +=1
    return -1

name ="bar"
list = [["foo", 1], ["bar", 2], ["baz", 3]]
new_list=[]
for item in list:
    new_list.append(item[0])
print(new_list)
try:
    location= new_list.index(name)
except:
    location=-1
print (location)

это объясняет, если строка не находится в списке, если ее нет в списке, то location = -1


поскольку списки Python основаны на нуле, мы можем использовать встроенную функцию zip следующим образом:

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

где "сена" список и "иглы" - это элемент, искать.

(Примечание: здесь мы повторяем использование i для получения индексов, но если нам нужно сосредоточиться на элементах, мы можем переключиться на j.)


на это есть более функциональный ответ.

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

Python index() метод выдает ошибку, если элемент не найден, что отстой!

поэтому вместо этого вы можете сделать его похожим на indexOf() функция JavaScript, которая возвращает -1 если элемент не найден:

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

Поиск индекса элемента x в список L:

idx = L.index(x) if (x in L) else -1

для тех, кто приходит с другого языка, как я, может быть, с простым циклом легче понять и использовать его:

mylist = ["foo", "bar", "baz", "bar"]
newlist = enumerate(mylist)
for index, item in newlist:
  if item == "bar":
    print(index, item)

Я благодарен за Итак, что именно делает enumerate?. Это помогло мне понять.


Если производительность вызывает беспокойство:

в многочисленных ответах упоминается, что встроенный метод list.index(item) метод является алгоритмом O(n). Это нормально, если вам нужно выполнить в этот раз. Но если вам нужно получить доступ к индексам элементов несколько раз, имеет смысл сначала создать словарь (O(n)) пар элемент-индекс, а затем получить доступ к индексу в O(1) каждый раз, когда вам это нужно.

если вы уверены, что элементы в списке не повторялись, вы можете легко:

myList = ["foo", "bar", "baz"]

# Create the dictionary
myDict = dict((e,i) for i,e in enumerate(myList))

# Lookup
myDict["bar"] # Returns 1
# myDict.get("blah") if you don't want an error to be raised if element not found.

если у вас могут быть дубликаты элементов, и вам нужно вернуть все их индексы:

from collections import defaultdict as dd
myList = ["foo", "bar", "bar", "baz", "foo"]

# Create the dictionary
myDict = dd(list)
for i,e in enumerate(myList):
    myDict[e].append(i)

# Lookup
myDict["foo"] # Returns [0, 4]

есть две возможности если в списке нет повторяющихся элементов, которые вы должны проверить индекс

 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]

тогда вы получите список индексов как o / p, Как [1,3]


как указано @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. Установить через > pip install more_itertools.