З огляду на список ["foo", "bar", "baz"]
та елемент у списку "bar"
, як я можу отримати його index ( 1
) у Python?
З огляду на список ["foo", "bar", "baz"]
та елемент у списку "bar"
, як я можу отримати його index ( 1
) у Python?
Відповіді:
>>> ["foo", "bar", "baz"].index("bar")
1
Довідково: Структури даних> Докладніше про списки
Зверніть увагу , що в той час як це , можливо , самий чистий спосіб відповісти на цей питання , як запитав , index
є досить слабким компонентом list
API, і я не можу згадати останній раз , коли я використовував його в гніві. Мені в коментарях було зазначено, що оскільки ця відповідь широко посилається, її слід зробити більш повною. Деякі застереження щодо list.index
наступного. Напевно, спочатку варто переглянути документацію на це:
list.index(x[, start[, end]])
Повернути індекс на основі нуля у списку першого елемента, значення якого дорівнює x . Піднімає a,
ValueError
якщо такого елемента немає.Необов'язкові аргументи початок і кінець інтерпретуються як у позначенні фрагмента і використовуються для обмеження пошуку певним підпорядком списку. Повернений індекс обчислюється відносно початку повної послідовності, а не аргументу початку.
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
Якщо елемент може бути відсутнім у списку, вам слід також
item in my_list
(чистий, читабельний підхід) абоindex
виклик у try/except
блок, який ловить ValueError
(можливо, швидше, принаймні, коли список для пошуку довгий, а елемент зазвичай присутній.)index()
це майже на 90% швидше, ніж розуміння списку проти списків цілих чисел.
Одне, що дуже корисно для вивчення 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()
(що майже такий же підхід, як і перерахування):
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()
повертає перший індекс вартості!
| покажчик (...)
| L.index (значення, [старт, [стоп]]) -> ціле число - поверне перший показник значення
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
Навіщо писати функції з обробкою виключень, якщо мова надає методи робити те, що ви хочете самі?
Якщо ви хочете, щоб усі індекси, ви можете використовувати 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),)
Це зрозуміле, читабельне рішення.
Виявлення індексу елемента дано список, що містить його в 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
немає:
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]
Так, ви можете використовувати розуміння списку і з перерахуванням, але це, на мій погляд, не настільки елегантно - ви робите тести на рівність у Python, а не дозволяєте вбудованому коду, написаному на C, обробляти його:
>>> [i for i, value in enumerate(l) if value == 'bar']
[1, 3]
Проблема 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
), і вони в основному використовуються при синтаксичному розборі (і користувальницькому інтерфейсі у випадку Idle).
Хоча для цього є випадки використання, вони є досить рідкісними. Якщо ви виявили, що шукаєте цю відповідь, запитайте себе, чи є те, що ви робите, найбільш пряме використання інструментів, наданих мовою для ваших випадків використання.
Усі індекси з 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')
За допомогою перерахування (alist) ви можете зберігати перший елемент (n), що є індексом списку, коли елемент x дорівнює тому, що ви шукаєте.
>>> alist = ['foo', 'spam', 'egg', 'foo']
>>> foo_indexes = [n for n,x in enumerate(alist) if x=='foo']
>>> foo_indexes
[0, 3]
>>>
Ця функція приймає елемент і список як аргументи і повертає позицію елемента в списку, як ми бачили раніше.
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
Ще один варіант
>>> 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]
>>>
... як підтвердження існування елемента до отримання індексу. Приємно в цьому підході функція завжди повертає список індексів - навіть якщо це порожній список. Він також працює з рядками.
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]
>>>
І тепер, переглянувши це питання та всі відповіді, я розумію, що саме це запропонував FMc у своїй попередній відповіді . У той час, коли я спочатку відповідав на це питання, я навіть не бачив цієї відповіді, тому що не розумів її. Я сподіваюся, що мій дещо докладніший приклад допоможе зрозуміти.
Якщо один рядок коду вище, як і раніше , не має для вас сенсу, я настійно рекомендую вам «зрозуміти список пітонів» Google і відвідайте кілька хвилин, щоб ознайомитись. Це лише одна з безлічі потужних функцій, які радують використання Python для розробки коду.
Варіант відповіді від 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]}
>>>
Ви також можете використовувати це як один вкладиш, щоб отримати всі індекси для одного запису. Немає гарантій ефективності, хоча я використав набір (a), щоб зменшити кількість викликів лямбда.
Пошук індексу елемента x у списку L:
idx = L.index(x) if (x in L) else -1
Оскільки списки Python засновані на нулі, ми можемо використовувати вбудовану функцію zip наступним чином:
>>> [i for i,j in zip(range(len(haystack)), haystack) if j == 'needle' ]
де "стог сіна" - це перелік, а "голка" - предмет, який потрібно шукати.
(Примітка. Тут ми повторюємо за допомогою i, щоб отримати індекси, але якщо нам потрібно скоріше зосередитись на елементах, ми можемо перейти до j.)
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
index()
Метод Python видає помилку, якщо елемент не був знайдений. Тож замість цього ви можете зробити його подібним до indexOf()
функції JavaScript, яка повертається, -1
якщо елемент не знайдено:
try:
index = array.index('search_keyword')
except ValueError:
index = -1
На це є більш функціональна відповідь.
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))))))
Scala
/ любителів функціонального програмування
Дамо назву 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
Для тих, хто походить з іншої мови, як я, можливо, за допомогою простого циклу це легше зрозуміти та використовувати:
mylist = ["foo", "bar", "baz", "bar"]
newlist = enumerate(mylist)
for index, item in newlist:
if item == "bar":
print(index, item)
Я вдячний за те, що саме перераховує? . Це допомогло мені зрозуміти.
Якщо ви збираєтесь знайти індекс один раз, то використовуючи метод "індекс", це добре. Однак якщо ви збираєтеся шукати ваші дані не раз, то рекомендую використовувати модуль бісект . Майте на увазі, що за допомогою даних бісект-модуля необхідно сортувати дані. Так ви сортуєте дані один раз, а потім можете використовувати бісект. Використання модуля бісектії на моїй машині приблизно в 20 разів швидше, ніж використання методу індексу.
Ось приклад коду з використанням синтаксису Python 3.8 та вище:
import bisect
from timeit import timeit
def bisect_search(container, value):
return (
index
if (index := bisect.bisect_left(container, value)) < len(container)
and container[index] == value else -1
)
data = list(range(1000))
# value to search
value = 666
# times to test
ttt = 1000
t1 = timeit(lambda: data.index(value), number=ttt)
t2 = timeit(lambda: bisect_search(data, value), number=ttt)
print(f"{t1=:.4f}, {t2=:.4f}, diffs {t1/t2=:.2f}")
Вихід:
t1=0.0400, t2=0.0020, diffs t1/t2=19.60
У численних відповідях згадується, що вбудований метод 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]
Як вказує @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
.
за допомогою словника, де спершу обробляйте список, а потім додайте до нього індекс
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]
на мою думку, ["foo", "bar", "baz"].index("bar")
це добре, але його недостатньо! Тому що якщо "бар" не є в словнику, підвищений. ValueError
Отже, ви можете використовувати цю функцію:
def find_index(arr, name):
try:
return arr.index(name)
except ValueError:
return -1
if __name__ == '__main__':
print(find_index(["foo", "bar", "baz"], "bar"))
і результат:
1
а якщо ім'я не було arr, функція return -1.для прикладу:
друк (find_index (["foo", "bar", "baz"], "fooo"))
-1
l = [1, 2]; find_index(l, 3)
що повернеться -1
і l[find_index(l, 3)]
повернеться 2
. -1 - погано повертатись, просто повернути None.
"bar"
, [2] Усі індекси"bar"
?