给定一个列表[“foo”、“bar”、“baz”]和列表“bar”中的一个项,如何获取其索引1?


当前回答

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

有关列表的内置.index()方法,请参阅文档:

list.index(x[,start[,end]])返回值等于x的第一项列表中从零开始的索引。如果没有该项,则引发ValueError。可选参数start和end被解释为切片符号,用于将搜索限制在列表的特定子序列。返回的索引是相对于完整序列的开头而不是start参数计算的。

注意事项

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

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

只有使用不同的数据结构才能完全避免这个问题。但是,如果已知元素在列表的某个部分内,则可以使用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万个元素。

仅返回第一个匹配项的索引

对索引的调用按顺序搜索列表,直到找到匹配项,然后停止。如果该值可能出现多次,并且需要所有索引,则索引无法解决问题:

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

如果这是一个问题,请首先使用my_list中的项显式检查,或者根据需要使用try/except处理异常。

显式检查简单易读,但它必须再次迭代列表。参见Python中的EAFP原理是什么?以获取有关此选择的更多指导。

其他回答

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

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

大多数答案解释了如何找到一个索引,但如果项目多次出现在列表中,它们的方法不会返回多个索引。使用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()的小解决方案(与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

不要。如果您确实需要,请使用列表中的.index(item…)方法。然而,这需要线性的时间,如果你发现自己正在努力,你可能会滥用列表来做一些你不应该做的事情。

最有可能的是,您关心1)整数和项目之间的双向映射,或2)在已排序的项目列表中查找项目。

对于第一个,使用一对字典。如果您需要一个库来实现这一点,请使用双向库。

对于第二个,使用可以正确利用列表排序这一事实的方法。使用python中内置的平分模块。

如果您希望在排序列表中插入项目,也不应使用排序列表。使用内置的heapq模块或使用sortedcontainers库将已排序的需求弱化为堆。

使用一个不是为你想做的事情而设计的数据结构是不好的做法。使用一个与你给它的任务相匹配的数据结构,既会向读者传达你想做特定的事情,也会使你的解决方案在实践中更快/更具可扩展性。

另一种选择

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

它只使用python函数array.index()和简单的Try/Except,如果在列表中找到记录,则返回该记录的位置,如果没有在列表中发现,则返回-1(就像在JavaScript中使用函数indexOf())。

fruits = ['apple', 'banana', 'cherry']

try:
  pos = fruits.index("mango")
except:
  pos = -1

在这种情况下,“mango”不在列表水果中,因此pos变量为-1,如果我搜索了“cherry”,pos变量将为2。