开发者

matlab fxn: find contiguous regions and return bounds in struct array

开发者 https://www.devze.com 2022-12-19 03:24 出处:网络
This is half a question and half a challenge to the matlab gurus out there: I\'d like to have a function take in a logical array (false/true) and give the beginning and ending of all the contiguous re

This is half a question and half a challenge to the matlab gurus out there: I'd like to have a function take in a logical array (false/true) and give the beginning and ending of all the contiguous regions containing trues, in a struct array.

Something like this:

b = getBounds([1 0 0 1 1 1 0 0 0 1 1 0 0])

should return

b = 3x1 struct array with fields:  
beg   
end

and

>> b(2)

ans = 

   beg: 4

   end: 6

I already have an implementation, but I don't really know h开发者_如何学Goow to deal with struct arrays well so I wanted to ask how you would do it - I have to go through mat2cell and deal, and when I have to deal with much larger struct arrays it becomes cumbersome. Mine looks like this:

df = diff([0 foo 0]);

a = find(df==1); l = numel(a); 
a = mat2cell(a',ones(1,l)) 
[s(1:l).beg] = deal(a{:});

b = (find(df==-1)-1); 
b = mat2cell(b',ones(1,l)) 
[s(1:l).end] = deal(b{:});


I don't see why you are using mat2cell, etc. You are making too much of the problem.

Given a boolean row vector V, find the beginning and end points of all groups of ones in the sequence.

V = [1 0 0 1 1 1 0 0 0 1 1 0 0];

You get most of it from diff. Thus

D = diff(V);
b.beg = 1 + find(D == 1);

This locates the beginning points of all groups of ones, EXCEPT for possibly the first group. So add a simple test.

if V(1)
  b.beg = [1,b.beg];
end

Likewise, every group of ones must end before another begins. So just find the end points, again worrying about the last group if it will be missed.

b.end = find(D == -1);
if V(end)
  b.end(end+1) = numel(V);
end

The result is as we expect.

b
b = 
    beg: [1 4 10]
    end: [1 6 11]

In fact though, we can do all of this even more easily. A simple solution is to always append a zero to the beginning and end of V, before we do the diff. See how this works.

D = diff([0,V,0]);
b.beg = find(D == 1);
b.end = find(D == -1) - 1;

Again, the result is as expected.

b
b = 
    beg: [1 4 10]
    end: [1 6 11]

By the way, I might avoid the use of end here, even as a structure field name. It is a bad habit to get into, using matlab keywords as variable names, even if they are only field names.


This is what I went with:

df = diff([0 foo 0]);
s = struct('on',num2cell(find(df==1)), ...
    'off',num2cell(find(df==-1)-1));

I forgot about num2cell and the nice behavior of struct with cell arrays.

0

精彩评论

暂无评论...
验证码 换一张
取 消