首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何更有效地实现这种阵列算法?

如何更有效地实现这种阵列算法?
EN

Stack Overflow用户
提问于 2020-07-05 22:16:20
回答 3查看 187关注 0票数 0

假设我有相同长度的n = 3列表,例如:

R1 = [7,5,8,6,0,6,7]

R2 = [8,0,2,2,0,2,2]

R3 = [1,7,5,9,0,9,9]

我需要找到第一个索引t,它验证n = 3,下面是一个句点p = 2的条件。编辑:句号p的意思是连续“方框”的数目。

  • R1[t] >= 5, R1[t+1] >= 5.在这里,t +p -1 = t+1,我们只需要验证两个盒子tt+1。如果p等于3,则需要验证tt+1t+2。请注意,我们测试的数字总是相同的,对于每个索引,我们总是测试它是否大于5。对于所有"boxes".
  • R2[t] >= 2, R2[t+1] >= 2
  • R3[t] >= 9, R3[t+1] >= 9

,条件总是相同的。

总共存在3 *p条件。

在这里,我要寻找的t5 (索引从0开始)。

这样做的基本方法是使用for循环循环所有索引。如果为某些索引t找到条件,则将其存储在某个局部变量temp中,并验证索引在t+1t+p -1之间的每个元素的条件仍然有效。如果在检查时,我们找到一个不满足条件的索引,我们就会忘记temp,然后继续前进。

如果我有大列表(比如10000个元素),那么在中最有效的方法是什么?有比for循环更有效的方法吗?

EN

回答 3

Stack Overflow用户

发布于 2020-07-05 23:40:31

由于您的所有条件都是相同的(>=),我们可以利用这一点。

此解决方案适用于任意数量的条件和任意大小的分析窗口,而不使用for循环。

您有一个数组:

代码语言:javascript
复制
>>> R = np.array([R1, R2, R3]).T                                                                                                                                                                         
>>> R
array([[7, 8, 1],
       [5, 0, 7],
       [8, 2, 5],
       [6, 2, 9],
       [0, 0, 0],
       [6, 2, 9],
       [7, 2, 9]]

你有阈值:

代码语言:javascript
复制
>>> thresholds = [5, 2, 9]

因此,您可以检查条件在哪里得到满足:

代码语言:javascript
复制
>>> R >= thresholds
array([[ True,  True, False],
       [ True, False, False],
       [ True,  True, False],
       [ True,  True,  True],
       [False, False, False],
       [ True,  True,  True],
       [ True,  True,  True]])

他们在同一时间相遇的地方:

代码语言:javascript
复制
>>> R_cond = np.all(R >= thresholds, axis=1)
>>> R_cond
array([False, False, False,  True, False,  True,  True])

从这里开始,您希望满足给定窗口的条件。

我们将利用布尔值可以加在一起的事实,并使用卷积来应用窗口:

代码语言:javascript
复制
>>> win_size = 2
>>> R_conv = np.convolve(R_cond, np.ones(win_size), mode="valid")
>>> R_conv
array([0., 0., 1., 1., 1., 2.])

在满足窗口范围内所有条件的索引处,结果数组的值将等于win_size

因此,让我们检索第一个索引:

代码语言:javascript
复制
>>> index = np.where(R_conv == win_size)[0][0]
>>> index
5

如果不存在这样的索引,它将引发一个IndexError,我让您处理这个问题。

因此,作为一个单线函数,它给出了:

代码语言:javascript
复制
def idx_conditions(arr, thresholds, win_size, condition):
    return np.where(
        np.convolve(
            np.all(condition(arr, thresholds), axis=1),
            np.ones(win_size),
            mode="valid"
        )
        == win_size
    )[0][0]

我将条件作为参数添加到函数中,以便更通用。

代码语言:javascript
复制
>>> from operator import ge
>>> idx_conditions(R, thresholds, win_size, ge)
5
票数 2
EN

Stack Overflow用户

发布于 2020-07-05 22:31:07

这可能是一种方式:

代码语言:javascript
复制
R1 = [7,5,8,6,0,6,7]

R2 = [8,0,2,2,0,2,2]

R3 = [1,7,5,9,0,9,9]

for i,inext in zip(range(len(R1)),range(len(R1))[1:]):
    if (R1[i]>=5 and R1[inext]>=5)&(R2[i]>=2 and R2[inext]>=2)&(R3[i]>=9 and R3[inext]>=9):
        print(i)

输出:

代码语言:javascript
复制
5

编辑:泛化可以是:

代码语言:javascript
复制
def foo(ls,conditions):
    index=0
    for i,inext in zip(range(len(R1)),range(len(R1))[1:]):
        if all((ls[j][i]>=conditions[j] and ls[j][inext]>=conditions[j])  for j in range(len(ls))):
            index=i
    return index


R1 = [7,5,8,6,0,6,7]

R2 = [8,0,2,2,0,2,2]

R3 = [1,7,5,9,0,9,9]

R4 = [1,7,5,9,0,1,1]

R5 = [1,7,5,9,0,3,3]



conditions=[5,2,9,1,3]
ls=[R1,R2,R3,R4,R5]

print(foo(ls,conditions))

输出:

代码语言:javascript
复制
5

而且,如果数组多次匹配条件,则可以返回索引列表:

代码语言:javascript
复制
def foo(ls,conditions):
    index=[]
    for i,inext in zip(range(len(R1)),range(len(R1))[1:]):
        if all((ls[j][i]>=conditions[j] and ls[j][inext]>=conditions[j])  for j in range(len(ls))):
            print(i)
            index.append(i)
    return index


R1 = [6,7,8,6,0,6,7]

R2 = [2,2,2,2,0,2,2]

R3 = [9,9,5,9,0,9,9]

R4 = [1,1,5,9,0,1,1]

R5 = [3,3,5,9,0,3,3]

conditions=[5,2,9,1,3]
ls=[R1,R2,R3,R4,R5]

print(foo(ls,conditions))

输出:

代码语言:javascript
复制
[0,5]
票数 1
EN

Stack Overflow用户

发布于 2020-07-05 22:38:24

下面是一个使用numpy的解决方案,没有for循环:

代码语言:javascript
复制
import numpy as np
R1 = np.array([7,5,8,6,0,6,7])
R2 = np.array([8,0,2,2,0,2,2])
R3 = np.array([1,7,5,9,0,9,9])
a = np.logical_and(np.logical_and(R1>=5,R2>=2),R3>=9)
np.where(np.logical_and(a[:-1],a[1:]))[0].item()

输出

代码语言:javascript
复制
5

编辑:

Generalization

假设您有一个列表( R )和一个条件列表( c )

代码语言:javascript
复制
R = [[7,5,8,6,0,6,7],
     [8,0,2,2,0,2,2],
     [1,7,5,9,0,9,9]]
c = [5,2,9]

首先,我们将它们转换为numpy数组。重塑(-1,1)将c转换为列矩阵,这样我们就可以在>=运算符中使用pythons广播功能。

代码语言:javascript
复制
R = np.array(R)
c = np.array(c).reshape(-1,1)
R>=c

output:
array([[ True,  True,  True,  True, False,  True,  True],
       [ True, False,  True,  True, False,  True,  True],
       [False, False, False,  True, False,  True,  True]])

然后,我们使用reduce函数在所有行之间执行逻辑操作

代码语言:javascript
复制
a = np.logical_and.reduce(R>=c)
a
output:
array([False, False, False,  True, False,  True,  True])

接下来,我们通过删除a的第一个和最后一个元素来创建两个数组,并在它们之间执行一个逻辑&这表明哪两个后续元素满足所有列表中的条件:

代码语言:javascript
复制
np.logical_and(a[:-1],a[1:])
output:
array([False, False, False, False, False,  True])

现在np.where只显示True元素的索引

代码语言:javascript
复制
np.where(np.logical_and(a[:-1],a[1:]))[0].item()
output:
5
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62746907

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档