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

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

Ответ 1

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

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

Предостережения

Обратите внимание, что хотя это, пожалуй, самый чистый способ ответить на заданный вопрос, index является довольно слабым компонентом API-интерфейса list, и я не могу вспомнить последний раз, когда я использовал его в гневе. В комментариях было указано, что, поскольку этот ответ в значительной степени упоминается, его следует сделать более полным. Ниже list.index некоторые оговорки о 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), поскольку первый должен искать только 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 (возможно, быстрее, по крайней мере, когда список поиска длинный, и элемент обычно присутствует.)

Ответ 2

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

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

class list(object)
 ...

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

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

Ответ 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

Ответ 4

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

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

Ответ 5

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

| Индекс (...)
 | L.index(значение, [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"])

Ответ 6

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

# 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

Ответ 7

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

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

Ответ 8

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

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

Ответ 9

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

[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

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

Ответ 10

Если вы хотите все индексы, то вы можете использовать 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),)

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

Ответ 11

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

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

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

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

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)

Лучшее перемещение данных с помощью pandas

Если у вас есть pandas, вы можете легко получить эту информацию с помощью объекта 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]

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

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

Является ли это проблемой XY?

Проблема XY спрашивает о вашем попытке решения, а не о вашей реальной проблеме.

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

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

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

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

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

Я не помню, чтобы я нуждался в list.index, сам. Тем не менее, я просмотрел стандартную библиотеку Python, и я вижу для этого отличные возможности.

В нем есть много и много применений в 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)

Кажется, что эти обычаи имеют общий характер: они, похоже, работают с списками ограниченных размеров (важно из-за времени поиска O (n) для list.index), и они в основном используются при разборе (и пользовательский интерфейс в случай Idle).

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

Ответ 12

Все индексы с функцией 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')

Ответ 13

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

С помощью 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

Ответ 14

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

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

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

Ответ 15

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

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

Ответ 16

А сейчас нечто соверешнно другое...

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

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

Обновить

После еще одного года развития 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 в своем более раннем ответе. В то время, когда я первоначально ответил на этот вопрос, я даже не видел этого ответа, потому что я этого не понимал. Я надеюсь, что мой несколько более подробный пример поможет понять.

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

Ответ 17

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

>>> 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), чтобы уменьшить количество раз, когда вызывается лямбда.

Ответ 18

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

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

Ответ 19

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

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

Ответ 20

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

Ответ 21

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

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

где "haystack" - это список, о котором идет речь, и "игла" - это предмет, который нужно искать.

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

Ответ 22

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

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

Ответ 23

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

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

Ответ 24

Давайте дадим имя lst списку, который у вас есть. Можно преобразовать список lst в numpy array. А затем используйте numpy.where, чтобы получить индекс выбранного элемента в списке. Следующее - способ, которым вы будете это реализовывать.

import numpy as np

lst = ["foo", "bar", "baz"]  #lst: : 'list' data type
print np.where( np.array(lst) == 'bar')[0][0]

>>> 1

Ответ 25

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

 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]

Ответ 26

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

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

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

Ответ 27

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

В многочисленных ответах упоминается, что встроенный метод метода 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]

Ответ 28

Как указывает @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.

Ответ 29

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

from collections import defaultdict

index_dict = defaultdict(list)    
word_list =  ['foo','bar','baz','bar','any', 'foo', 'much']

for word_index in range(len(word_list)) :
    index_dict[word_list[word_index]].append(word_index)

word_index_to_find = 'foo'       
print(index_dict[word_index_to_find])

# output :  [0, 5]