查找列表中项目的索引

给定一个列表["foo", "bar", "baz"]和列表"bar"中的一个项目,我如何获得它的索引1

5715782 次浏览

最简单的情况由列表的内置#0方法处理:

list.index(x[, start[, end]])

返回值等于x的第一个项目列表中从零开始的索引。如果没有这样的项目,则引发#0

可选参数开始结束被解释为切片记法,用于将搜索限制在列表的特定子序列中。返回的索引是相对于完整序列的开头而不是开始参数计算的。

因此,我们可以做到:

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

警告

列表长度的线性时间复杂度

index调用按顺序检查列表中的每个元素,直到找到匹配项。如果列表很长,并且不能保证值将接近开头,这会减慢代码速度。

这个问题只能通过使用不同的数据结构来完全避免。但是,如果已知元素在列表的某个部分内,则可以使用startend参数来缩小搜索范围。

例如:

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

第二个调用要快几个数量级,因为它只需要搜索10个元素,而不是所有100万。

只返回第一场比赛的索引

index的调用按顺序搜索列表,直到找到匹配项,停在那里。如果该值可能出现不止一次,并且需要所有索引,index无法解决问题:

>>> [1, 1].index(1) # the `1` index is not found.0

相反,使用列表推导或生成器表达式来进行搜索#0获取索引

>>> # A list comprehension gives a list of indices directly:>>> [i for i, e in enumerate([1, 2, 1]) if e == 1][0, 2]>>> # A generator comprehension gives us an iterable object...>>> g = (i for i, e in enumerate([1, 2, 1]) if e == 1)>>> # which can be used in a `for` loop, or manually iterated with `next`:>>> next(g)0>>> next(g)2

如果只有一个匹配项,列表理解和生成器表达式技术仍然有效,并且更具通用性。

如果没有匹配,则引发异常

如上所述,如果搜索的值不在列表中,使用.index将引发异常:

>>> [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,要么酌情使用try/except处理异常。

显式检查简单易读,但它必须第二次迭代列表。有关此选择的更多指导,请参阅Python中的EAFP原则是什么?

index()返回值的第一索引!

|index(…)
|L.index(value,[start,[Stop]]) -> integer--返回值的第一个索引

def all_indices(value, qlist):indices = []idx = -1while True:try:idx = qlist.index(value, idx+1)indices.append(idx)except ValueError:breakreturn indices
all_indices("foo", ["foo","bar","baz","foo"])
a = ["foo","bar","baz",'bar','any','much']
indexes = [index for index in range(len(a)) if a[index] == 'bar']

如果元素不在列表中,则会出现问题。此函数处理问题:

# 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_elementexcept ValueError:return 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

如果语言提供了自己想要的方法,为什么要编写带有异常处理的函数?

你可以跟我一起去

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

大多数答案都解释了如何找到一个索引,但如果项目多次出现在列表中,他们的方法不会返回多个索引。使用#0

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

这里还有另一个带有#0的小解决方案(与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']

来自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)来减少调用lambda的次数,但不能保证效率。

您必须设置一个条件来检查您正在搜索的元素是否在列表中

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

现在,对于完全不同的东西…

…就像在获取索引之前确认项目的存在一样。这种方法的好处是函数总是返回索引列表——即使它是一个空列表。它也适用于字符串。

def indices(l, val):"""Always returns a list containing the indices of val in the_list"""retval = []last = 0while val in l[last:]:i = l[last:].index(val)retval.append(last + i)last += i + 1return 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 darwinType "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 darwinType "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列表理解”,并花几分钟时间熟悉一下。这只是使用Python开发代码的众多强大功能之一。

此解决方案不如其他解决方案强大,但如果您是初学者并且只知道forloops,仍然可以找到项目的第一个索引,同时避免ValueError:

def find_element(p,t):i = 0for e in p:if e == t:return ielse:i +=1return -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=-1print (location)

这说明了如果字符串也不在列表中,如果它不在列表中,那么location = -1

#0函数的所有索引:

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

如果你想要所有的索引,那么你可以使用NumPy

import numpy as np
array = [1, 2, 1, 3, 4, 5, 1]item = 1np_array = np.array(array)item_index = np.where(np_array==item)print item_index# Out: (array([0, 2, 6], dtype=int64),)

这是一个清晰易读的解决方案。

获取列表中一个或多个(相同)项的所有出现次数和位置

使用enumerate(ist),当元素x等于您要查找的内容时,您可以存储作为列表索引的第一个元素(n)。

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

输出:

04

由于Python列表是从零开始的,我们可以使用zip内置函数,如下所示:

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

其中“干草堆”是有问题的列表,“针”是要查找的项目。

(注意:这里我们使用i迭代以获取索引,但如果我们需要关注项目,我们可以切换到j。

在Python中找到给定包含它的列表的项目的索引

对于列表["foo", "bar", "baz"]和列表"bar"中的项目,在Python中获取其索引(1)的最干净方法是什么?

当然,还有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

这样做的缺点是,您可能需要检查返回值isis 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)>>> series0    foo1    bar2    baz3    bardtype: object

比较检查将返回一系列布尔值:

>>> series == 'bar'0    False1     True2    False3     Truedtype: bool

通过下标表示法将该系列布尔值传递给该系列,您只需获得匹配的成员:

>>> series[series == 'bar']1    bar3    bardtype: object

如果只需要索引,index属性返回一系列整数:

>>> series[series == 'bar'].indexInt64Index([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相当冗长-我宁愿避免这种情况。

无论如何,我通常会迭代列表,所以我通常会保留一个指向任何有趣信息的指针,获取带枚举的索引。

如果你正在处理数据,你可能应该使用Pandas——它比我展示的纯Python变通方法有更优雅的工具。

我自己不记得需要list.index。然而,我已经浏览了Python标准库,我看到了它的一些很好的用途。

它在idlelib中有很多很多用途,用于GUI和文本解析。

keyword模块使用它来查找模块中的注释标记,以通过元编程自动重新生成其中的关键字列表。

在Lib/mailbox.py中,它似乎像有序映射一样使用它:

key_list[key_list.index(old)] = new

del key_list[key_list.index(key)]

在Lib/超文本传输协议/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情况下的UI)。

虽然有它的用例,但它们相当不常见。如果您发现自己在寻找这个答案,请问问自己,您正在做的是否是该语言为您的用例提供的工具的最直接使用。

对于像我这样来自另一种语言的人来说,也许用一个简单的循环更容易理解和使用它:

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

我很感激那么enumerate到底是做什么的呢?。这帮助我理解。

如果找不到项目,Pythonindex()方法会抛出错误。因此,您可以将其设置为类似于JavaScript的indexOf()函数,如果找不到项目,则返回-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))))))

在列表L中查找项目x的索引:

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

如果性能有问题:

大量回答提到list.index(item)方法的内置方法是O(n)算法,需要执行一次没关系。但是如果需要多次访问元素的索引,则更有意义的做法是先创建一个项目-索引对的字典(O(n)),然后每次需要时以O(1)的位置访问索引。

如果您确定列表中的项目永远不会重复,您可以轻松地:

myList = ["foo", "bar", "baz"]
# Create the dictionarymyDict = dict((e,i) for i,e in enumerate(myList))
# LookupmyDict["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 ddmyList = ["foo", "bar", "bar", "baz", "foo"]
# Create the dictionarymyDict = dd(list)for i,e in enumerate(myList):myDict[e].append(i)
# LookupmyDict["foo"] # Returns [0, 4]

正如@TerryA所指出的,许多答案讨论了如何找到一个索引。

#0是一个第三方库,具有在可迭代对象中定位多个索引的工具。

鉴于

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]

另请参阅#0的更多选项。通过#1安装。

让我们将名称lst添加到您拥有的列表中。可以将列表lst转换为numpy array。然后使用numpy.where获取列表中所选项目的索引。以下是您将实现它的方式。

import numpy as np
lst = ["foo", "bar", "baz"]  #lst: : 'list' data typeprint np.where( np.array(lst) == 'bar')[0][0]
>>> 1

使用字典,首先处理列表,然后将索引添加到其中

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]

如果您要查找一次索引,那么使用“index”方法就可以了。但是,如果您要多次搜索数据,那么我建议使用二分法模块。请记住,使用Bisect模块数据必须进行排序。所以您对数据进行一次排序,然后您就可以使用Bisect了。在我的机器上使用二分法模块比使用index方法快20倍。

以下是使用Python 3.8及以上语法的代码示例:

import bisectfrom timeit import timeit
def bisect_search(container, value):return (indexif (index := bisect.bisect_left(container, value)) < len(container)and container[index] == value else -1)
data = list(range(1000))# value to searchvalue = 666
# times to testttt = 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

对于一个可比

# Throws ValueError if nothing is foundsome_list = ['foo', 'bar', 'baz'].index('baz')# some_list == 2

自定义谓词

some_list = [item1, item2, item3]
# Throws StopIteration if nothing is found# *unless* you provide a second parameter to `next`index_of_value_you_like = next(i for i, item in enumerate(some_list)if item.matches_your_criteria())

通过谓词查找所有项目的索引

index_of_staff_members = [i for i, user in enumerate(users)if user.is_staff()]

该值可能不存在,因此为了避免此ValueError,我们可以检查该值是否确实存在于列表中。

list =  ["foo", "bar", "baz"]
item_to_find = "foo"
if item_to_find in list:index = list.index(item_to_find)print("Index of the item is " + str(index))else:print("That word does not exist")

它只是使用python函数array.index(),如果在列表中找到记录,它会返回记录的位置,如果在列表中找不到,它会返回-1(就像在JavaScript中使用函数indexOf()一样)。

fruits = ['apple', 'banana', 'cherry']
try:pos = fruits.index("mango")except:pos = -1

在这种情况下,“芒果”不存在于列表fruits中,因此pos变量为-1,如果我搜索了“樱桃”,pos变量将为2。

简单选项:

a = ["foo", "bar", "baz"][i for i in range(len(a)) if a[i].find("bar") != -1]

我发现这两个解决方案更好,我自己尝试过

>>> expences = [2200, 2350, 2600, 2130, 2190]>>> 2000 in expencesFalse>>> expences.index(2200)0>>> expences.index(2350)1>>> index = expences.index(2350)>>> expences[index]2350
>>> try:...     print(expences.index(2100))... except ValueError as e:...     print(e)...2100 is not in list>>>

Pythonic方式将使用enumerate,但您也可以使用operator模块中的#1。请注意,这将提高#3如果#4不在#5中。

>>> from operator import indexOf>>>>>>>>> help(indexOf)Help on built-in function indexOf in module _operator:
indexOf(a, b, /)Return the first index of b in a.
>>>>>>>>> indexOf(("foo", "bar", "baz"), "bar") # with tuple1>>> indexOf(["foo", "bar", "baz"], "bar") # with list1

python中的某些结构包含一个索引方法,可以很好地解决这个问题。

'oi tchau'.index('oi')     # 0['oi','tchau'].index('oi') # 0('oi','tchau').index('oi') # 0

参考文献:

在列表中

在元组中

在字符串中

text = ["foo", "bar", "baz"]target = "bar"
[index for index, value in enumerate(text) if value == target]

对于一个小的元素列表,这会很好。但是,如果list包含大量元素,最好对应用二进制使用O(log n)运行时复杂度搜索.

我的朋友,我做了最简单的代码来解决你的问题。当你收到大量代码时,我在这里为你提供两行代码,这一切都归功于python中index()函数的帮助。

LIST = ['foo' ,'boo', 'shoo']print(LIST.index('boo'))

输出:

1

我希望我已经给了你最好和最简单的答案,这可能会对你有很大的帮助。

在查找列表中项目的索引时,列表理解是获得紧凑实现的最佳选择。

a_list = ["a", "b", "a"]print([index for (index , item) in enumerate(a_list) if item == "a"])
me = ["foo", "bar", "baz"]me.index("bar")

您可以将此应用于列表中的任何成员以获取其索引

可以使用zip()函数来获取列表中值的索引。代码可能是;

list1 = ["foo","bar","baz"]for index,value in zip(range(0,len(list1)),list1):if value == "bar":print(index)

尝试以下代码:

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

请参阅:https://www.programiz.com/python-programming/methods/list/index