如何识别至少10个相邻';1';在MATLAB中,向量中的s?

如何识别至少10个相邻';1';在MATLAB中,向量中的s?,matlab,vector,Matlab,Vector,如何识别从仅由0和1组成的第一个元素开始的向量中至少10个相邻“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的系列开始。您可以使用arrayfun执行Matlab风格的“数组理解”: 摘要:循环比arrayfun快一英里 这里有一种使用经典旧循环的方法: function x = test_loop(A) for ii = 1:numel(A)-9

如何识别从仅由0和1组成的第一个元素开始的向量中至少10个相邻“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的系列开始。

您可以使用
arrayfun
执行Matlab风格的“数组理解”:


摘要:循环比
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
与经典
对于
循环的性能:

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)的基准测试结果:

尺寸为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

您可以使用regexp:

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)
这种“内存密集型”解决方案不是更快吗?(此处无法检查,不再有Matlab:')()

编辑: 那么:

helper = cumsum(A);
result = 1 + find(helper - [helper(11:end) nan(1,10)]==-10,1)

也应该很好

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

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

@请注意,arrayfun只是一个伪装的for循环。另外,您应该有
find(b==1,1)
才能正确执行此操作。=)我同意。我猜,隐藏的原因是Matlab的匿名函数比普通for循环慢(for循环的性能不再是原来的样子)。事实上,在编写性能敏感代码时应该注意这一点:+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];

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)
helper = cumsum(A);
result = 1 + find(helper - [helper(11:end) nan(1,10)]==-10,1)
temp = diff([0 A 0]);
start = find(temp == 1);
finish = find(temp == -1);
result = start(find(finish - start >= 10, 1, 'first'));