如何在MATLAB中的向量中识别至少10个相邻 1的第一次出现?

时间:2016-06-23 00:55:50

标签: matlab vector

如何识别从第1个元素开始的向量中至少10个相邻的#1的第一次出现,第1个元素仅由0和1组成?

A=[0 1 0 0 0 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 0 1]

代码应返回A的索引(本例中为12),其中1的序列开始。

5 个答案:

答案 0 :(得分:5)

摘要:循环次数增加arrayfun一英里!

这是使用经典旧循环的方法:

function x = test_loop(A)
for ii = 1:numel(A)-9
    x = ii*(all(A(ii:ii+9)));
    if x
        break;
    end   
end
end

现在,我们来调查arrayfun与经典for的效果 - 循环:

arrayfun方法:

test_array = @(A)find(arrayfun(@(x) all(A(x:x+9)==ones(1,10)), 1:numel(A)-9)==1,1)

A = [0 1 0 0 0 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 0 1];
B = repmat(A,1,10);   %% 1x300 array

f = @() test_array(A);
g = @() test_loop(A);

您的阵列的基准测试结果(1x30):

timeit(f)
ans =
   2.1397e-04

timeit(g)
ans =
   2.6224e-05

对于大小为1x300的数组的基准测试结果:

f = @() test_array(B);
g = @() test_loop(B);

timeit(f)
ans =
    0.0021

timeit(g)
ans =
   2.6598e-05

如果在向量中找到第一个序列,则循环会慢一点,但仍然比arrayfun快:

B(1:220) = 0;

f = @() test_array(B);
g = @() test_loop(B);

timeit(f)
ans =
    0.0021
timeit(g)
ans =
   4.5033e-04

修改

为什么每次迭代都会将计数器递增1?以下循环大约是for循环的两倍,具体取决于序列在向量中出现的位置以及零之间的间距。

它仍然比conv慢,但认为值得分享:

function x = test_loop(A)    
ii = 1;
x = false;
while ~x
    k = find(A(ii:ii+9)~=1, 1, 'last');
    x = isempty(k)*ii;
    ii = ii + k;
end
end

答案 1 :(得分:3)

您可以使用arrayfun进行Matlab风格的"阵列理解":

A=[0 1 0 0 0 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 0 1]
b = arrayfun(@(x) all(A(x:x+9)==ones(1,10)), 1:numel(A)-9)
find(b==1)

答案 2 :(得分:3)

你可以使用正则表达式:

A = [0 1 0 0 0 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 0 1];
N = 10;
result = regexp(char(A+'0'), ['1{' num2str(N) '}'], 'once');

或卷积:

A = [0 1 0 0 0 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 0 1];
N = 10;
result = find(conv(2*A-1, ones(1,N), 'valid')==N, 1)

答案 3 :(得分:2)

使用diff和find的可能解决方案:

temp = diff([0 A 0]);
start = find(temp == 1);
finish = find(temp == -1);
result = start(find(finish - start >= 10, 1, 'first'));

答案 4 :(得分:1)

那种“内存密集型”解决方案不是更快吗? (不能在这里查看,不再有Matlab:'()

delete candidate.skills;

修改 怎么样:

A = [0 1 0 0 0 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 0 1];

len_A = length(A);

helper = repmat(A,10,2);

helper = helper(bsxfun(@plus,bsxfun(@plus,(0:10-1)',0:len_A-1)*10,(1:10)'));

result = find(all(helper(:,1:end-10)),1)

也应该很好