如何查找列表中所有出现的元素?


377

index()只会给出列表中第一个出现的项目。有没有整齐的技巧可以返回列表中的所有索引?


1
这个问题让我有些困惑:您是要在多维列表的所有级别中递归搜索项,还是只想搜索列表的顶层出现项?
Anderson Green

22
我认为应该有一个完全做到这一点的列表方法。
otocan '17

Answers:


544

您可以使用列表理解:

indices = [i for i, x in enumerate(my_list) if x == "whatever"]

3
在较旧的python上,将filter()用于基本相同的功能。
Gleno

44
列表推导显示在python的2.0,版本enumerate为2.3。是的,如果您的Python很古老,请使用filter()
Steven Rumbalski 2011年

2
此技术无法在多维数组中找到所有出现的项目。例如,print([i for i, x in enumerate([[1,1],[0,1]]) if x == 1])返回[]而不是[[0, 1], [0, 0], [1, 1]]
2014年

9
@AndersonGreen:术语“多维数组”表示一种数据结构,该数据结构在其每个轴上均具有统一的大小。在普通的Python中没有这样的数据结构。有列表列表,但是它们与“多维数组”有很大不同。如果需要后者,则应考虑使用NumPy,它允许您执行类似(a == 1).nonzero()NumPy array的操作a
Sven Marnach 2014年

2
@MadmanLee如果您想快速进行操作,请使用NumPy。请参见JoshAdel
Georgy

117

虽然不是直接解决列表问题的方法,但numpy对于此类事情确实很有帮助:

import numpy as np
values = np.array([1,2,3,1,2,4,5,6,3,2,1])
searchval = 3
ii = np.where(values == searchval)[0]

返回:

ii ==>array([2, 8])

与其他一些解决方案相比,这对于包含大量元素的列表(数组)而言可能会更快。


2
我注意到最后的[0]会将数组转换为字符串。我很好奇您为什么选择这样做。
阿米莉亚

5
@amelia [0]是必需的,因为会where返回一个元组(array([2, 8], dtype=int64),)
Winand

1
嘿@Winand我输入了[0],但仍然得到了两个部分。这是我的代码:(nrg.local_logs.all_id_resp_address是一个列表)“ ste =” 199.38.164.165“ value = np.where(nrg.local_logs.all_id_resp_address == ste)[0]”如果您能告诉我,我将很高兴我做错了什么
Tomer

2
@Tomer首先不all_id_resp_address应该。np.arraylist
温南德

1
@Tomer你试图比较liststr,很明显,你传递Falsenp.wherenp.array与smth 比较时。您将获得一个布尔值数组。然后np.where找到True该数组所有值的位置。
温南德

29

使用list.index以下解决方案:

def indices(lst, element):
    result = []
    offset = -1
    while True:
        try:
            offset = lst.index(element, offset+1)
        except ValueError:
            return result
        result.append(offset)

enumerate对于大型列表,它比使用的列表理解要快得多。如果您已经拥有阵列,它也比numpy解决方案要慢得多,否则转换的成本将超过速度增益(在具有100、1000和10000个元素的整数列表上进行测试)。

注意:基于Chris_Rands的注释的注意事项:如果结果足够稀疏,但是如果列表中有许多正在搜索的元素实例(大于列表的15%),则此解决方案比列表理解要快。 ,在包含1000个整数列表的测试中),列表理解速度更快。


3
您说这比列表组合要快,您能显示出证明这一点的时间吗?
Chris_Rands

4
这是很久以前的事,我可能使用timeit.timeit了随机生成的列表。不过,这很重要,我想那可能就是你问的原因。当时我还没有想到,但是只有在结果足够稀疏的情况下,速度提升才是正确的。我只是用一个充满要搜索元素的列表进行了测试,它比列表理解要慢得多。
Paulo Almeida

18

怎么样:

In [1]: l=[1,2,3,4,3,2,5,6,7]

In [2]: [i for i,val in enumerate(l) if val==3]
Out[2]: [2, 4]

10
occurrences = lambda s, lst: (i for i,e in enumerate(lst) if e == s)
list(occurrences(1, [1,2,3,1])) # = [0, 3]

8

more_itertools.locate 查找满足条件的所有项目的索引。

from more_itertools import locate


list(locate([0, 1, 1, 0, 1, 0, 0]))
# [1, 2, 4]

list(locate(['a', 'b', 'c', 'b'], lambda x: x == 'b'))
# [1, 3]

more_itertools是第三方库> pip install more_itertools


1
如果将此lib添加到conda- conda install
forge中,

4

针对所有情况的另一种解决方案(对不起,如果重复的话):

values = [1,2,3,1,2,4,5,6,3,2,1]
map(lambda val: (val, [i for i in xrange(len(values)) if values[i] == val]), values)

4

或使用range(python 3):

l=[i for i in range(len(lst)) if lst[i]=='something...']

对于(python 2):

l=[i for i in xrange(len(lst)) if lst[i]=='something...']

然后(两种情况):

print(l)

符合预期。



2

您可以创建一个defaultdict

from collections import defaultdict
d1 = defaultdict(int)      # defaults to 0 values for keys
unq = set(lst1)              # lst1 = [1, 2, 2, 3, 4, 1, 2, 7]
for each in unq:
      d1[each] = lst1.count(each)
else:
      print(d1)

2

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

使用enumerate(alist)可以存储第一个元素(n),即元素x等于要查找的内容时列表的索引。

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

这个答案对我来说是最容易在现有代码中实现的。
Ryan Harris

2

使用for-loop

  • 带有enumerate列表理解的答案更高效,更pythonic,但是,此答案针对的是可能不允许使用某些内置函数的学生
  • 创建一个空列表, indices
  • 使用创建循环for i in range(len(x)):,从本质上遍历索引位置列表[0, 1, 2, 3, ..., len(x)-1]
  • 在循环中,任何添加i,这里x[i]是一个比赛value,以indices
def get_indices(x: list, value: int) -> list:
    indices = list()
    for i in range(len(x)):
        if x[i] == value:
            indices.append(i)
    return indices

n = [1, 2, 3, -50, -60, 0, 6, 9, -60, -60]
print(get_indices(n, -60))

>>> [4, 8, 9]
  • 功能get_indices带有类型提示。在这种情况下,列表s n是一堆int,因此我们搜索value,也定义为int

使用while-loop.index

  • 使用.indextry-except用于错误处理,因为ValueError如果value不在列表中,则会出现a 。
def get_indices(x: list, value: int) -> list:
    indices = list()
    i = 0
    while True:
        try:
            # find an occurrence of value and update i to that index
            i = x.index(value, i)
            # add i to the list
            indices.append(i)
            # advance i by 1
            i += 1
        except ValueError as e:
            break
    return indices

print(get_indices(n, -60))
>>> [4, 8, 9]

您的自定义get_indeices速度比普通列表理解要快(〜15%)。我想弄清楚。
特拉维斯

1

如果您使用的是Python 2,则可以通过以下方式实现相同的功能:

f = lambda my_list, value:filter(lambda x: my_list[x] == value, range(len(my_list)))

my_list您要获取其索引的列表在哪里,是要value搜索的值。用法:

f(some_list, some_element)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.