Python 如何获取另一个列表中某个列表项的索引?
假设我有以下清单:Python 如何获取另一个列表中某个列表项的索引?,python,list,numpy,Python,List,Numpy,假设我有以下清单: l = [5,6,7,8,9,10,5,15,20] m = [10,5] 我想在l中获得m的索引。我使用列表理解来实现这一点: [(i,i+1) for i,j in enumerate(l) if m[0] == l[i] and m[1] == l[i+1]] 输出:[(5,6)] 但是如果我在m中有更多的数字,我觉得这不是正确的方法。那么,在Python或NumPy中有什么简单的方法吗 另一个例子: l = [5,6,7,8,9,10,5,15,20,50,16,
l = [5,6,7,8,9,10,5,15,20]
m = [10,5]
我想在l
中获得m
的索引。我使用列表理解来实现这一点:
[(i,i+1) for i,j in enumerate(l) if m[0] == l[i] and m[1] == l[i+1]]
输出:[(5,6)]
但是如果我在m
中有更多的数字,我觉得这不是正确的方法。那么,在Python或NumPy中有什么简单的方法吗
另一个例子:
l = [5,6,7,8,9,10,5,15,20,50,16,18]
m = [10,5,15,20]
输出应为:
[(5,6,7,8)]
您基本上是在另一个列表中查找列表的起始索引 方法#1:解决方法之一是在我们正在搜索的列表中创建元素的滑动窗口,给我们一个
2D
数组,然后简单地使用NumPy broadcasting
对搜索列表中先前获得的2D
滑动窗口版本的每一行执行广播比较。因此,一种方法是-
# strided_app is from https://stackoverflow.com/a/40085052/
def strided_app(a, L, S ): # Window len = L, Stride len/stepsize = S
nrows = ((a.size-L)//S)+1
n = a.strides[0]
return np.lib.stride_tricks.as_strided(a, shape=(nrows,L), strides=(S*n,n))
def pattern_index_broadcasting(all_data, search_data):
n = len(search_data)
all_data = np.asarray(all_data)
all_data_2D = strided_app(np.asarray(all_data), n, S=1)
return np.flatnonzero((all_data_2D == search_data).all(1))
out = np.squeeze(pattern_index_broadcasting(l, m)[:,None] + np.arange(len(m)))
样本运行-
In [340]: l = [5,6,7,8,9,10,5,15,20,50,16,18]
...: m = [10,5,15,20]
...:
In [341]: np.squeeze(pattern_index_broadcasting(l, m)[:,None] + np.arange(len(m)))
Out[341]: array([5, 6, 7, 8])
In [342]: l = [5,6,7,8,9,10,5,15,20,50,16,18,10,5,15,20]
...: m = [10,5,15,20]
...:
In [343]: np.squeeze(pattern_index_broadcasting(l, m)[:,None] + np.arange(len(m)))
Out[343]:
array([[ 5, 6, 7, 8],
[12, 13, 14, 15]])
方法#2:另一种方法是获得滑动窗口,然后获得要搜索的数据和要搜索的数据的行级标量视图,这样我们就可以使用1D
数据,如下所示-
# view1D is from https://stackoverflow.com/a/45313353/
def view1D(a, b): # a, b are arrays
a = np.ascontiguousarray(a)
void_dt = np.dtype((np.void, a.dtype.itemsize * a.shape[1]))
return a.view(void_dt).ravel(), b.view(void_dt).ravel()
def pattern_index_view1D(all_data, search_data):
a = strided_app(np.asarray(all_data), L=len(search_data), S=1)
a0v, b0v = view1D(np.asarray(a), np.asarray(search_data))
return np.flatnonzero(np.in1d(a0v, b0v))
out = np.squeeze(pattern_index_view1D(l, m)[:,None] + np.arange(len(m)))
2020版
在寻找更简单/紧凑的方法时,我们可以研究scikit图像的内置滑动窗口。我假设数组作为不太混乱的代码的输入。对于作为输入的列表,我们必须使用np.asarray()
,如前所示
方法#3:基本上是模式(pattern)索引(broadcasting)
的一种派生方法以视图(u as)窗口
为一行,其中a
为较大的数据,b
为要搜索的数组-
from skimage.util import view_as_windows
np.flatnonzero((view_as_windows(a,len(b))==b).all(1))[:,None]+np.arange(len(b))
方法#4:对于a
中b
中的少量匹配,我们可以通过从b
中查找第一个元素匹配来优化,以减少搜索的数据集大小-
mask = a[:-len(b)+1]==b[0]
mask[mask] = (view_as_windows(a,len(b))[mask]).all(1)
out = np.flatnonzero(mask)[:,None]+np.arange(len(b))
方法#5:对于小型b
,我们可以简单地为b
中的每个元素运行一个循环,并执行按位和缩减
-
mask = np.bitwise_and.reduce([a[i:len(a)-len(b)+1+i]==b[i] for i in range(len(b))])
out = np.flatnonzero(mask)[:,None]+np.arange(len(b))
最简单的方法(使用纯Python)是迭代这些项,然后首先只检查第一个项是否匹配。这样可以避免在不需要时进行子列表比较。根据l
的内容,这可能会比NumPy广播解决方案更出色:
def func(haystack, needle): # obviously needs a better name ...
if not needle:
return
# just optimization
lengthneedle = len(needle)
firstneedle = needle[0]
for idx, item in enumerate(haystack):
if item == firstneedle:
if haystack[idx:idx+lengthneedle] == needle:
yield tuple(range(idx, idx+lengthneedle))
>>> list(func(l, m))
[(5, 6, 7, 8)]
如果您对速度感兴趣,我会检查进近的性能(借用我的设置):
如果您的l
和m
是列表,我的功能在所有尺寸上都优于NumPy解决方案:
但是,如果您将这些作为numpy阵列,那么在使用Divakars numpy解决方案时,对于大型阵列(大小>1000个元素),您将获得更快的结果:
def func(haystack, needle): # obviously needs a better name ...
if not needle:
return
# just optimization
lengthneedle = len(needle)
firstneedle = needle[0]
for idx, item in enumerate(haystack):
if item == firstneedle:
if haystack[idx:idx+lengthneedle] == needle:
yield tuple(range(idx, idx+lengthneedle))
>>> list(func(l, m))
[(5, 6, 7, 8)]
只是强调@MSeifert的方法当然也可以在
numpy
中实现:
def pp(h,n):
nn = len(n)
NN = len(h)
c = (h[:NN-nn+1]==n[0]).nonzero()[0]
if c.size==0: return
for i,l in enumerate(n[1:].tolist(),1):
c = c[h[i:][c]==l]
if c.size==0: return
return np.arange(c[0],c[0]+nn)
在多次出现的情况下,索引值应该是多少<代码>5在您的示例中…我希望它按特定顺序检查列表。如果没有找到订单,ohk会有一个空的列表。我不确定副本是否能解决您的问题。如果没有,请告诉我。:)被NumPy标记后,您可能希望利用它的矢量化功能。重新打开,是的。我想要的是numpy数组方法。它是如此精确和快速。它以纳秒为单位输出。哇。先生,如果我想得到所有的重复序列,而不是第一个。@Bharathshetty将
np.argmax
替换为np.flatnonzero
。让我来编辑。@Bharathshetty就像我说的,让我来编辑:)编辑完成后告诉我:)他们都很好,先生。第一种方法比第二种方法快一点。基准图非常好。非常感谢你的链接。我在我这边已经证实了这一点,但是矢量化解决方案的阈值变得更好了,在我这边的200个元素上,阵列数据。我不得不使用列表(查找子列表\u索引(a,b))
,以确保我们正在做同样的事情。@divaker你说得对。我混合了我的函数(列表)的最快情况和你的函数(数组)的最快情况。请注意,如果要将数组转换为列表,则tolist
将比list
快得多(在大多数情况下,系数为2-5)。如果您对所有函数的numpy数组都感兴趣,我将在稍后更新答案。:)