我知道Python列表有一个方法可以返回某个对象的第一个索引:

>>> xs = [1, 2, 3]
>>> xs.index(2)
1

NumPy数组也有类似的东西吗?


当前回答

注意:这是python 2.7版本

您可以使用lambda函数来处理这个问题,它既适用于NumPy数组,也适用于列表。

your_list = [11, 22, 23, 44, 55]
result = filter(lambda x:your_list[x]>30, range(len(your_list)))
#result: [3, 4]

import numpy as np
your_numpy_array = np.array([11, 22, 23, 44, 55])
result = filter(lambda x:your_numpy_array [x]>30, range(len(your_list)))
#result: [3, 4]

你可以用

result[0]

获取筛选元素的第一个索引。

对于python 3.6,使用

list(result)

而不是

result

其他回答

要在任何标准上建立索引,你可以这样做:

In [1]: from numpy import *
In [2]: x = arange(125).reshape((5,5,5))
In [3]: y = indices(x.shape)
In [4]: locs = y[:,x >= 120] # put whatever you want in place of x >= 120
In [5]: pts = hsplit(locs, len(locs[0]))
In [6]: for pt in pts:
   .....:         print(', '.join(str(p[0]) for p in pt))
4, 4, 0
4, 4, 1
4, 4, 2
4, 4, 3
4, 4, 4

这里有一个快速函数,它可以做list.index()所做的事情,只是如果没有找到它,它不会引发异常。注意——这在大型数组上可能非常慢。如果你想把它作为一个方法,你也可以把它拼凑到数组上。

def ndindex(ndarray, item):
    if len(ndarray.shape) == 1:
        try:
            return [ndarray.tolist().index(item)]
        except:
            pass
    else:
        for i, subarray in enumerate(ndarray):
            try:
                return [i] + ndindex(subarray, item)
            except:
                pass

In [1]: ndindex(x, 103)
Out[1]: [4, 0, 3]

对于一维排序数组,使用numpy会更简单、更有效。searchsorted,返回一个NumPy整数(位置)。例如,

arr = np.array([1, 1, 1, 2, 3, 3, 4])
i = np.searchsorted(arr, 3)

只要确保数组已经排序

还要检查返回的索引i是否包含被搜索的元素,因为searchsorted的主要目标是找到应该插入元素以保持顺序的索引。

if arr[i] == 3:
    print("present")
else:
    print("not present")

找到了另一个循环解决方案:

new_array_of_indicies = []

for i in range(len(some_array)):
  if some_array[i] == some_value:
    new_array_of_indicies.append(i)
    

如果你想用它作为其他东西的索引,如果数组是可广播的,你可以使用布尔索引;不需要显式索引。要做到这一点,绝对最简单的方法是基于真值进行索引。

other_array[first_array == item]

任何布尔运算都可以:

a = numpy.arange(100)
other_array[first_array > 50]

非零方法也接受布尔值:

index = numpy.nonzero(first_array == item)[0][0]

两个0分别表示索引元组(假设first_array是1D)和索引数组中的第一项。

L.index (x)返回最小的I,使得I是x在列表中第一次出现的索引。

可以放心地假设,Python中的index()函数的实现使它在找到第一个匹配后停止,这将导致最佳的平均性能。

要在NumPy数组中找到第一个匹配后停止的元素,请使用迭代器(ndenumerate)。

In [67]: l=range(100)

In [68]: l.index(2)
Out[68]: 2

NumPy数组:

In [69]: a = np.arange(100)

In [70]: next((idx for idx, val in np.ndenumerate(a) if val==2))
Out[70]: (2L,)

注意,如果没有找到元素,index()和next方法都会返回一个错误。使用next,可以使用第二个参数在未找到元素时返回一个特殊值,例如:

In [77]: next((idx for idx, val in np.ndenumerate(a) if val==400),None)

NumPy中还有其他函数(argmax, where和nonzero)可用于在数组中查找元素,但它们都有一个缺点,即遍历整个数组查找所有出现的元素,因此无法优化以查找第一个元素。还要注意,where和非零返回数组,因此需要选择第一个元素来获取索引。

In [71]: np.argmax(a==2)
Out[71]: 2

In [72]: np.where(a==2)
Out[72]: (array([2], dtype=int64),)

In [73]: np.nonzero(a==2)
Out[73]: (array([2], dtype=int64),)

时间比较

只是检查对于大型数组,当搜索项位于数组的开头时,使用迭代器的解决方案更快(在IPython shell中使用%timeit):

In [285]: a = np.arange(100000)

In [286]: %timeit next((idx for idx, val in np.ndenumerate(a) if val==0))
100000 loops, best of 3: 17.6 µs per loop

In [287]: %timeit np.argmax(a==0)
1000 loops, best of 3: 254 µs per loop

In [288]: %timeit np.where(a==0)[0][0]
1000 loops, best of 3: 314 µs per loop

这是一个开放的NumPy GitHub问题。

参见:Numpy:快速找到第一个值索引