提问



对于列表["foo", "bar", "baz"]和列表"bar"中的项目,如何在Python中获取其索引(1)?

最佳参考


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


参考:数据结构>更多关于列表[98]


警告遵循



请注意,虽然这可能是回答问题的最简洁方法,indexlist API的一个相当弱的组件,我不记得最后一个我在愤怒中使用它。在评论中我已经指出,因为这个答案被大量引用,所以应该更加完整。关于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)快大约五个数量级,因为前者只需要搜索10个条目,而后者搜索一百万:


>>> 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 "<stdin>", line 1, in <module>
ValueError: 2 is not in list


如果该项目可能不在列表中,您应该



  1. 首先使用item in my_list(干净,可读的方法)或
  2. 进行检查
  3. index调用包裹在try/except块中,该块可以捕获ValueError(可能更快,至少当搜索列表很长时,该项目通常存在。)


其它参考1


学习Python真正有用的一件事是使用交互式帮助功能:


>>> help(["foo", "bar", "baz"])
Help on list object:

class list(object)
 ...

 |
 |  index(...)
 |      L.index(value, [start, [stop**]) -> integer -- return first index of value
 |


这通常会引导您找到您正在寻找的方法。

其它参考2


大多数答案解释了如何找到单个索引,但如果项目在列表中多次,则它们的方法不会返回多个索引。使用enumerate():[99]


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()的另一个小解决方案(与枚举几乎相同):[100]


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()返回第一个值的索引!



  |指数(...)点击
   | 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


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


# 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

其它参考6


a = ["foo","bar","baz",'bar','any','much']

indexes = [index for index in range(len(a)) if a[index] == 'bar']

其它参考7


您必须设置条件以检查您要搜索的元素是否在列表中


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

其它参考8


这里提出的所有功能都重现了固有的语言行为,但却模糊了正在发生的事情。


[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


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

其它参考9


如果你想要所有索引,那么你可以使用NumPy:[101]


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


它是清晰易读的解决方案。

其它参考10



  

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


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



嗯,当然,有索引方法,它返回第一次出现的索引:


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


使用pandas更好的数据



如果您有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


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


>>> 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问题是询问您尝试的解决方案而不是实际问题。[102]



为什么你认为你需要给定列表中的元素的索引?


如果您已经知道该值,为什么要关注它在列表中的位置?


如果值不在那里,那么抓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/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)


这些用法似乎有共同之处在于它们似乎在约束大小的列表上运行(因为list.index的O(n)查找时间很重要),并且它们主要用于解析(以及UI中的UI)空闲的情况)。


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

其它参考11


具有zip功能的所有索引:[104]


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

其它参考12


你可以随便去


a = [**'hand', 'head'], ['phone', 'wallet'], ['lost', 'stock'**]
b = ['phone', 'lost']

res = [**x[0] for x in a].index(y) for y in b]

其它参考13


另外一个选择


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

其它参考14


来自FMc和user7177的答案的变体将给出一个可以返回任何条目的所有索引的dict:


>>> 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被调用的次数,但是效率没有保证。

其它参考15


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



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

其它参考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]
>>> 


更新



经过另一年的低调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 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在他之前的回答中所建议的。当我最初回答这个问题时,我甚至没有看到那个答案,因为我不理解它。我希望我的一些更冗长的例子能够帮助理解。


如果上面的单行代码对你没有意义,我强烈建议你使用Googlepython list comprehension并花几分钟时间熟悉自己。这只是其中的一个强大的功能,使用Python开发代码令人高兴。

其它参考17


这个解决方案没有其他解决方案那么强大,但是如果你是一个初学者并且只知道for循环,它仍然可以在避免ValueError时找到项目的第一个索引:


def find_element(p,t):
    i = 0
    for e in p:
        if e == t:
            return i
        else:
            i +=1
    return -1

其它参考18


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

其它参考19


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


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


其中haystack是有问题的列表,needle是要查找的项目。


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

其它参考20


如果找不到项目,Python index()方法会抛出错误,这很糟糕!


所以你可以使它类似于JavaScript的indexOf()函数,如果找不到该项,它将返回-1:


    try:
        index = array.index('search_keyword')
    except ValueError:
        index = -1

其它参考21


对此有一个更实用的答案。


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

其它参考22


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


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

其它参考23


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


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


我很感谢那么枚举究竟做了什么?。这有助于我理解。[107]