Поиск индекса элемента по списку, содержащему его в Python - PullRequest
2683 голосов
/ 07 октября 2008

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

Ответы [ 28 ]

3876 голосов
/ 07 октября 2008
>>> ["foo", "bar", "baz"].index("bar")
1

Ссылка: Структуры данных> Больше в списках

Предостережения следуют

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

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

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

class list(object)
 ...

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

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

492 голосов
/ 20 июня 2013

Большинство ответов объясняют, как найти отдельный индекс , но их методы не возвращают несколько индексов, если элемент находится в списке несколько раз. Используйте 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
139 голосов
/ 25 июня 2013

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

 indexes = [i for i,x in enumerate(xs) if x == 'foo']
120 голосов
/ 30 августа 2011

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"])
72 голосов
/ 16 апреля 2013

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

# 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
67 голосов
/ 21 августа 2012
a = ["foo","bar","baz",'bar','any','much']

indexes = [index for index in range(len(a)) if a[index] == 'bar']
47 голосов
/ 26 мая 2014

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

if 'your_element' in mylist:
    print mylist.index('your_element')
else:
    print None
39 голосов
/ 16 мая 2013

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

[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

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

34 голосов
/ 17 ноября 2015

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

Это понятное, читабельное решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...