我有一个数组(比如说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但带有向量。
答案 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)
工作原理
将x
与N
个向量进行对比,并在第一次找到结果等于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