如何在列表中找到给定项目的索引?
- 2024-11-21 08:33:00
- admin 原创
- 5
问题描述:
给定一个列表["foo", "bar", "baz"]
和列表中的一个项目"bar"
,如何获取其索引1
?
解决方案 1:
>>> ["foo", "bar", "baz"].index("bar")
1
请参阅列表内置方法的文档:.index()
list.index(x[, start[, end]])
返回列表中第一个值等于x的项目的从零开始的索引。
ValueError
如果不存在这样的项目,则引发 a。可选参数start和end按照切片符号进行解释,用于将搜索限制在列表的特定子序列中。返回的索引是相对于完整序列的开头而不是 start 参数计算的。
注意事项
列表长度的线性时间复杂度
调用index
会按顺序检查列表中的每个元素,直到找到匹配项。如果列表很长,并且无法保证值位于开头附近,则这可能会减慢代码速度。
只有使用不同的数据结构才能完全避免此问题。但是,如果已知元素位于列表的某个部分内,则可以使用start
和end
参数来缩小搜索范围。
例如:
>>> 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
相反,使用列表推导或生成器表达式来执行搜索,并enumerate
获取索引:
>>> # 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 原理是什么?
解决方案 2:
大多数答案解释了如何找到单个索引,但是如果该项目多次出现在列表中,则它们的方法不会返回多个索引。使用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
解决方案 3:
获取所有索引:
indexes = [i for i, x in enumerate(xs) if x == 'foo']
解决方案 4:
index()
返回值的第一个索引!
| 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"])
解决方案 5:
a = ["foo","bar","baz",'bar','any','much']
indexes = [index for index in range(len(a)) if a[index] == 'bar']
解决方案 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:
您必须设置一个条件来检查您搜索的元素是否在列表中
if 'your_element' in mylist:
print mylist.index('your_element')
else:
print None
解决方案 8:
如果您想要所有索引,那么您可以使用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),)
这是一个清晰、易读的解决方案。
解决方案 9:
在 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
这样做的缺点是您可能需要检查返回值是否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 进行更好的数据处理
如果你有熊猫,你可以很容易地用 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
如果您只想要索引,索引属性将返回一系列整数:
>>> 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 标准库,发现它有一些很好的用途。
它在 GUI 和文本解析等方面有非常多的用途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 的情况下用于 UI)。
虽然有用例,但这些用例并不常见。如果您正在寻找这个答案,请问问自己,您正在做的事情是否是针对您的用例最直接地使用该语言提供的工具。
解决方案 10:
这里提出的所有功能都重现了固有的语言行为,但却掩盖了正在发生的事情。
[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
如果语言本身提供了执行您想要的操作的方法,那么为什么还要编写具有异常处理的函数呢?
解决方案 11:
获取列表中一个或多个(相同)项目的所有出现位置
使用 enumerate(alist),当元素 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)
输出:
0
4
解决方案 12:
me = ["foo", "bar", "baz"]
me.index("bar")
您可以将其应用于列表中的任何成员以获取他们的索引
解决方案 13:
所有具有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')
解决方案 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]
>>>
当然可以使用上述代码;然而,获得相同行为的更惯用的方法是使用列表推导以及 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 开发代码变得非常有趣。
解决方案 17:
以下是使用 Python 函数的两行代码index()
:
LIST = ['foo' ,'boo', 'shoo']
print(LIST.index('boo'))
输出:1
解决方案 18:
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 的调用次数,但效率并不能保证。
解决方案 19:
查找列表 L 中项目 x 的索引:
idx = L.index(x) if (x in L) else -1
解决方案 20:
如果未找到该项目, Pythonindex()
方法将抛出错误。因此,您可以将其设置为类似于indexOf()
JavaScript 函数,-1
如果未找到该项目,则返回:
def indexof( array, elem):
try:
return array.index(elem)
except ValueError:
return -1
解决方案 21:
这个解决方案不如其他解决方案那么强大,但是如果你是初学者并且只了解for
循环,仍然可以找到项目的第一个索引,同时避免 ValueError:
def find_element(p,t):
i = 0
for e in p:
if e == t:
return i
else:
i +=1
return -1
解决方案 22:
列表推导是获取紧凑实现以查找列表中项目索引的最佳选择。
a_list = ["a", "b", "a"]
print([index for (index , item) in enumerate(a_list) if item == "a"])
解决方案 23:
该值可能不存在,因此为了避免此 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")
上述代码的预期输出:Index of the item is 0
更有效的替代方法:
由于调用item_to_find in list
和list.index(item_to_find)
要进行两次搜索,因此可以使用 , 将其缩短为仅一次操作try
。except
由于当项目不在列表中时它会抛出 ValueError,我们可以使用该消息打印用户信息以指示出了什么问题。
以下代码可以作为增强使用。
list = ["foo", "bar", "baz"]
item_to_find = "fooz"
try:
index = list.index(item_to_find)
print("Index of the item is " + str(index))
except ValueError as error:
print(f'Item couldn\'t be found because {error}.')
上述代码的预期输出是:Item couldn't be found because 'fooz' is not in list
解决方案 24:
它只是使用 python 函数array.index()
和简单的 Try / Except,如果在列表中找到记录,则返回记录的位置,如果在列表中找不到记录,则返回 -1(类似于在使用函数的 JavaScript 上indexOf()
)。
fruits = ['apple', 'banana', 'cherry']
try:
pos = fruits.index("mango")
except:
pos = -1
在这种情况下,“mango”不在列表中,fruits
所以pos
变量为 -1,如果我搜索“cherry”,pos
变量就是 2。
解决方案 25:
对于一个可比较的
# Throws ValueError if nothing is found
some_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()]
解决方案 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],\n (list(filter(lambda x: x[1]==element, enumerate(lst))))))
解决方案 27:
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
解决方案 28:
由于 Python 列表是从零开始的,因此我们可以使用 zip 内置函数,如下所示:
>>> [i for i,j in zip(range(len(haystack)), haystack) if j == 'needle' ]
其中“haystack”是所讨论的列表,“needle”是要查找的项目。
(注意:这里我们使用 i 进行迭代来获取索引,但如果我们需要关注项目,我们可以切换到 j。)
解决方案 29:
如果担心性能:
许多答案都提到,方法的内置方法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]
解决方案 30:
如果您要查找一次索引,那么使用“索引”方法就可以了。但是,如果您要多次搜索数据,那么我建议使用二分模块。请记住,使用二分模块数据必须排序。因此,您只需对数据进行一次排序,然后就可以使用二分模块。在我的计算机上使用二分模块比使用索引方法快 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
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件