我有以下逻辑向量:
vect1 = [0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 0 1 1 0 0 0 1]
我想在此向量中找到所有1
值“簇”以及它们的起始和结束索引。对于输出,我希望能够提出类似的东西:
5 8
13 15
18 19
23 23
其中第一个数字是每个群集的“起始”索引,第二个数字是每个群集的“结束”索引。
编辑:我能够使用Shai的答案的修改版本来使用它:pv = [vect1 0];
sv = [0 pv(1:(end-1))];
ev = [pv(2:end) 0];
starting = find( pv - sv == 1 )
ending = find( pv - ev == 1 )
答案 0 :(得分:4)
这个问题几乎与this one重复。从那里调整我的答案:
vect1 = [0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 0 1 1 0 0 0 1];
v1 = (vect1(:)==1);
d = diff(v1);
output = [find([v1(1);d]==1) find([d;-v1(end)]==-1)]
返回
output =
5 8
13 15
18 19
23 23
find
的两次调用可以通过
[output,~] = find([[v1(1);d] [-d;v1(end)]]==1);
output = reshape(output,[length(output)/2 2]);
答案 1 :(得分:3)
要处理最后的1,用向量填充向量会更简单:
pv = [vect1 0];
sv = [0 pv];
ev = [pv(2:end) 0];
starting = find( pv - sv == 1 );
ending = find( pv - sv == -1 );
答案 2 :(得分:0)
这是我能想到的最简单的一个班轮
out = [find(diff([0 vect1 0])==1); find(diff([0 vect1 0])==-1)-1]'
答案 3 :(得分:0)
在Matlab文件交换上有一个运行长度编码函数,我用它来解决这类问题。这个解决方案的好处(即rle函数)是它在没有事先知道将重复哪些值的情况下找到重复的块。
encoded = rle(vect1);
summed = cumsum(encoded{2});
isOne = encoded{1}==1;
[summed(isOne)-encoded{2}(isOne)+1; summed(isOne)]'
请参阅: http://www.mathworks.com/matlabcentral/fileexchange/4955-rle-deencoding
或者(稍快)
blockEnds = [ find(vect1(1:end-1) ~= vect1(2:end)) length(vect1) ];
blockStarts = [ 1 blockEnds(1:end-1)+1];
isOne = vect1(blockEnds)==1;
[blockStarts(isOne); blockEnds(isOne)]'