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

3019
Eugene M 7 Окт 2008 в 05:39

27 ответов

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

12
bvanlew 28 Мар 2014 в 09:11

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

>>> 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
Mathitis2Software 29 Май 2013 в 19:17

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

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

class list(object)
 ...

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

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

881
davidavr 7 Окт 2008 в 13:19

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

С помощью 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
21
AkshayNevrekar 5 Ноя 2018 в 12:18

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

1
pylang 25 Сен 2018 в 15:47

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

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

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

2
Peter Mortensen 4 Июн 2018 в 20:55

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

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

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 для разработки кода.

15
MrWonderful 18 Июл 2018 в 10:01
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

5
AkshayNevrekar 13 Фев 2020 в 13:06

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

idx = L.index(x) if (x in L) else -1
7
Ketan 30 Янв 2019 в 17:36
a = ["foo","bar","baz",'bar','any','much']

indexes = [index for index in range(len(a)) if a[index] == 'bar']
75
savinson 31 Окт 2017 в 07:45

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

indexes = [i for i,x in enumerate(xs) if x == 'foo']
164
Arkistarvh Kltzuonstev 30 Июл 2019 в 11:17

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

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

res = [[x[0] for x in a].index(y) for y in b]
16
kiriloff 29 Май 2013 в 07:17

Давайте дадим имя 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
3
Siddharth Satpathy 28 Ноя 2018 в 06:42

Все индексы с 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')
22
Peter Mortensen 4 Июн 2018 в 20:50

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

if 'your_element' in mylist:
    print mylist.index('your_element')
else:
    print None
56
user3670684 26 Май 2014 в 04:26

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

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))))))
3
Peter Mortensen 4 Июн 2018 в 20:53

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

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]
0
sahasrara62 18 Мар 2019 в 09:32

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

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

38
Peter Mortensen 4 Июн 2018 в 20:26

В большинстве ответов объясняется, как найти один индекс , но их методы не возвращают несколько индексов, если элемент находится в списке несколько раз. Используйте 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
530
Boris 21 Янв 2020 в 13:04

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

# 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
81
tanzil 24 Апр 2017 в 10:00

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

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

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

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

5
Peter Mortensen 4 Июн 2018 в 20:56

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

def find_element(p,t):
    i = 0
    for e in p:
        if e == t:
            return i
        else:
            i +=1
    return -1
10
totallyhuman 12 Ноя 2017 в 06:07

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

В многочисленных ответах упоминается, что встроенный метод метода 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]
1
FatihAkici 10 Сен 2018 в 18:51

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

[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

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

43
KeyWeeUsr 24 Дек 2016 в 14:24

Чтобы предотвратить ValueError, вы можете сделать функцию для этого, хотя класс также будет работать.

def findInList(List, item):
   try:
      return List.index(item)
   except ValueError:
      return -1

Единственная проблема заключается в том, что это может привести к серьезной ошибке; То же самое относится и к другим номерам.
Однако, если он возвращает что-то кроме числа, он, вероятно, будет использоваться в качестве индекса списка и в любом случае неизбежно вызовет ошибку.

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

# python 3.x

class itemNotFoundInListError(Exception): 
    pass

def findInList(List, item):
   try:
      return List.index(item)
   except ValueError:
      raise itemNotFoundInListError(f"List `{List}` does not contain `{item}.`")
1
Sapphire_Brick 29 Окт 2019 в 22:27

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

try:
    index = array.index('search_keyword')
except ValueError:
    index = -1
4
Arkistarvh Kltzuonstev 30 Июл 2019 в 11:19

Поиск индекса элемента по списку, содержащему его в 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)

Лучшее копание данных с пандами

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

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

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

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

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

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

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

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

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

Если вы манипулируете данными, вам, вероятно, следует использовать панд - у которых гораздо более изящные инструменты, чем чисто обходные пути 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), и они в основном используются при разборе (и пользовательском интерфейсе в случай простоя).

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

31
Aaron Hall 2 Сен 2017 в 23:56