连续n次查找条件的真实情况

时间:2016-04-05 16:25:05

标签: arrays matlab

我有一个数组(比如说1和0),我想找到索引i,用于连续n次出现1次的第一个位置。

例如,

x = [0 0 1 0 1 1 1 0 0 0] ;

i = 5,n = 3,因为这是第一次'1'连续出现三次。

注意:我想找到连续n次出现的位置

 i = find(x,n,'first');

不正确,因为这会给我第一个n 1的索引。

它本质上是一个字符串搜索?例如findstr但带有向量。

4 个答案:

答案 0 :(得分:6)

您可以通过以下方式进行卷积:

x = [0 0 1 0 1 1 1 0 0 0];
N = 3;
result = find(conv(x, ones(1,N), 'valid')==N, 1)

工作原理

xN个向量进行对比,并在第一次找到结果等于N时。使用'valid'标志计算卷积以避免边缘效应,从而获得索引的正确值。

答案 1 :(得分:4)

我的另一个答案是生成缓冲区矩阵,其中此矩阵的每一行都是数组重叠n元素的邻域。创建之后,索引到数组并找到包含全1的第一行:

x = [0 0 1 0 1 1 1 0 0 0]; %// Example data
n = 3; %// How many times we look for duplication

%// Solution
ind = bsxfun(@plus, (1:numel(x)-n+1).', 0:n-1); %'
out = find(all(x(ind),2), 1);

第一行有点棘手。我们使用bsxfun生成大小为m x n的矩阵,其中m是重叠邻域的总数,而n是您要搜索的窗口的大小。这将生成一个矩阵,其中第一行从1枚举到n,第二行从2枚举到n+1,直到最后一行从numel(x)-n+1到{{1 }}。给定numel(x),我们有:

n = 3

这些索引将用于索引我们的数组>> ind ind = 1 2 3 2 3 4 3 4 5 4 5 6 5 6 7 6 7 8 7 8 9 8 9 10 ,对于您的示例,当我们直接索引到x时,它会生成以下缓冲区矩阵:

x

每一行都是>> x = [0 0 1 0 1 1 1 0 0 0]; >> x(ind) ans = 0 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 0 1 0 0 0 0 0 元素的重叠邻域。我们最终通过搜索给我们所有1的第一行结束。这是通过使用all并使用n作为第二个参数独立搜索每一行来完成的。如果一行中的每个元素都非零,则2生成all,或者在我们的情况下为1。然后我们与find结合以确定满足此约束的第一个非零位置......以及:

true

这告诉我们 >> out = find(all(x(ind), 2), 1) out = 5 的第五个位置是重复开始的x次。

答案 2 :(得分:2)

基于Rayryeng's approach,你也可以循环播放。对于短阵列大小,这肯定会慢一些,但是对于非常大的阵列大小,这并不能计算每种可能性,但是一旦找到第一个匹配就停止,因此会更快。您甚至可以使用基于初始数组长度的if语句来选择是使用bsxfun还是for循环。另请注意,自最新的MATLAB引擎更新以来,for循环速度相当快。

x = [0 0 1 0 1 1 1 0 0 0]; %// Example data
n = 3; %// How many times we look for duplication

for idx = 1:numel(x)-n
    if all(x(idx:idx+n-1))
        break
    end
end

此外,这可用于查找a首次出现:

x = [0 0 1 0 1 1 1 0 0 0 0 0 1 0 1 1 1 0 0 0 0 0 1 0 1 1 1 0 0 0]; %// Example data
n = 3; %// How many times we look for duplication
a = 2; %// number of desired matches
collect(1,a)=0; %// initialise output
kk = 1; %// initialise counter

for idx = 1:numel(x)-n
    if all(x(idx:idx+n-1))
        collect(kk) = idx;
        if kk == a
            break
        end
        kk = kk+1;
    end
end

a匹配后找到相同但关闭的内容。同样,这种方法仅在您的数组很大时才有用。

看到你commented是否可以找到最后一次出现:是的。和以前一样,只需向后运行循环:

for idx = numel(x)-n:-1:1
    if all(x(idx:idx+n-1))
        break
    end
end

答案 3 :(得分:1)

循环的一种可能性:

i = 0;
n = 3;

for idx = n : length(x)
    idx_true = 1;
    for sub_idx = (idx - n + 1) : idx
        idx_true = idx_true & (x(sub_idx));
    end
    if(idx_true)
        i = idx - n + 1;
        break
    end
end

if (i == 0)
    disp('No index found.')
else
    disp(i)
end