Index()将给出列表中第一个出现的项。是否有一个巧妙的技巧可以返回一个元素列表中的所有索引?


当前回答

There’s an answer using np.where to find the indices of a single value, which is not faster than a list-comprehension, if the time to convert a list to an array is included The overhead of importing numpy and converting a list to a numpy.array probably makes using numpy a less efficient option for most circumstances. A careful timing analysis would be necessary. In cases where multiple functions/operations will need to be performed on the list, converting the list to an array, and then using numpy functions will likely be a faster option. This solution uses np.where and np.unique to find the indices of all unique elements in a list. Using np.where on an array (including the time to convert the list to an array) is slightly slower than a list-comprehension on a list, for finding all indices of all unique elements. This has been tested on an 2M element list with 4 unique values, and the size of the list/array and number of unique elements will have an impact. Other solutions using numpy on an array can be found in Get a list of all indices of repeated elements in a numpy array Tested in [python 3.10.4, numpy 1.23.1] and [python 3.11.0, numpy 1.23.4]

import numpy as np
import random  # to create test list

# create sample list
random.seed(365)
l = [random.choice(['s1', 's2', 's3', 's4']) for _ in range(20)]

# convert the list to an array for use with these numpy methods
a = np.array(l)

# create a dict of each unique entry and the associated indices
idx = {v: np.where(a == v)[0].tolist() for v in np.unique(a)}

# print(idx)
{'s1': [7, 9, 10, 11, 17],
 's2': [1, 3, 6, 8, 14, 18, 19],
 's3': [0, 2, 13, 16],
 's4': [4, 5, 12, 15]}

%timeit在2M元素列表中,有4个唯一的str元素

# create 2M element list
random.seed(365)
l = [random.choice(['s1', 's2', 's3', 's4']) for _ in range(2000000)]

功能

def test1():
    # np.where: convert list to array and find indices of a single element
    a = np.array(l)
    return np.where(a == 's1')
    

def test2():
    # list-comprehension: on list l and find indices of a single element
    return [i for i, x in enumerate(l) if x == "s1"]


def test3():
    # filter: on list l and find indices of a single element
    return list(filter(lambda i: l[i]=="s1", range(len(l))))


def test4():
    # use np.where and np.unique to find indices of all unique elements: convert list to array
    a = np.array(l)
    return {v: np.where(a == v)[0].tolist() for v in np.unique(a)}


def test5():
    # list comprehension inside dict comprehension: on list l and find indices of all unique elements
    return {req_word: [idx for idx, word in enumerate(l) if word == req_word] for req_word in set(l)}

函数调用

%timeit test1()
%timeit test2()
%timeit test3()
%timeit test4()
%timeit test5()

python 3.10.4

214 ms ± 19.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
85.1 ms ± 1.48 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
146 ms ± 1.65 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
365 ms ± 11.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
360 ms ± 5.82 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

结果python 3.11.0

209 ms ± 15.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
70.4 ms ± 1.86 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
132 ms ± 4.65 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
371 ms ± 20.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
314 ms ± 15.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

其他回答

你可以使用枚举的列表推导式:

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

迭代器enumerate(my_list)为列表中的每一项生成对(index, item)。使用i, x作为循环变量目标,将这些对解包到索引i和列表项x中。我们向下筛选到所有符合条件的x,并选择这些元素的索引i。

如何:

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]

这里是使用np的时间性能比较。Where vs list_comprehension。好像是np。哪里的平均速度更快。

# np.where
start_times = []
end_times = []
for i in range(10000):
    start = time.time()
    start_times.append(start)
    temp_list = np.array([1,2,3,3,5])
    ixs = np.where(temp_list==3)[0].tolist()
    end = time.time()
    end_times.append(end)
print("Took on average {} seconds".format(
    np.mean(end_times)-np.mean(start_times)))
Took on average 3.81469726562e-06 seconds
# list_comprehension
start_times = []
end_times = []
for i in range(10000):
    start = time.time()
    start_times.append(start)
    temp_list = np.array([1,2,3,3,5])
    ixs = [i for i in range(len(temp_list)) if temp_list[i]==3]
    end = time.time()
    end_times.append(end)
print("Took on average {} seconds".format(
    np.mean(end_times)-np.mean(start_times)))
Took on average 4.05311584473e-06 seconds

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

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

或使用范围(python 3):

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

For (python 2):

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

然后(两种情况):

print(l)

不出所料。