在列表中找到项目的索引

内容来自 DOC https://q.houxu6.top/?s=在列表中找到项目的索引

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


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

查看列表的内置 .index() 方法的文档:

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

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

可选参数 startend 解释为切片符号,并用于将搜索限制到列表的特定子序列。返回的索引是相对于完整序列的开头计算的,而不是 start 参数。

注意事项

线性时间复杂度在列表长度上

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

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

>>> # 列表推导式直接给出索引列表:
>>> [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)
>>> # 可以使用 in 循环,或者使用 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 处理异常。

显式检查简单易懂,但必须再次遍历列表。有关此选择的更多指导,请参阅 What is the EAFP principle in Python?

posted @ 2023-10-16 21:11  小满独家  阅读(26)  评论(0)    收藏  举报