tags:

views:

189

answers:

2

Hi everyone, 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 how 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{:});

+5  A: 

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.

woodchips
One side note... If you want to create an *array of structures* instead of *one structure storing arrays*, you could do this: `b = struct('beg',num2cell(find(D == 1)),'end',num2cell(find(D == -1)-1));`
gnovice
i wanted to create the array of structures. this is pretty much what i needed, thanks.
johndashen
A: 

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.

johndashen

related questions