题目
对于列表 ["foo", "bar", "baz"]和在列表中的元素"bar",如何得到它的下标(1)
回答一
>>> ["foo", "bar", "baz"].index("bar")
1
注意事项
注意虽然这可能是对所问问题最简单的回答方法,index在list中支持很弱,以下是list.index的注意事项,一开始看下它的文档:
>>> print(list.index.__doc__)
L.index(value, [start, [stop]]) -> integer -- return first index of value.
Raises ValueError if the value is not present.
线性的时间复杂度
一个index将会按顺序检查列表中的每一个元素,直到找到相匹配的。如果列表很长,而且你不知道大致会出现在列表中的哪个位置,这种搜索方式可能成为瓶颈。这种情况下,你应该考虑另一种数据结构。注意如果你大致直到哪个位置能找到匹配值,你可以给index一个提示。例如,l.index(999_999, 999_990, 1_000_000)比直接使用l.index(999_999)大约快5个数量级,因为前者只需要搜索10个元素,后者将搜索100w个。
>>> 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 "", line 1, in >
ValueError: 2 is not in list
如果元素可能不在列表中,你应该
首先使用item in my_list(简单,可读)检查,或者
使用try/except包装index的调用,捕获ValueError异常(可能更快,至少要搜索的列表很长而且元素经常是存在的情况下是这样)。