user129412
user129412

Reputation: 775

Find number of consecutive elements before value changes (MATLAB)

I have a (row)vector of some size, containing the values 1,2 and 3. They are in there in no 'specific' order, so a sample of the array would be [1,1,1,1,2,2,2,1,1,2,2,3,3]. What I want to do is find the consecutive number of identical elements, but with some restrictions.

What I want is to make new arrays of which the elements denote:

So for the example I have given, the arrays would be

[4,2]
[3]
[2]
[]

I'm not sure how to tackle this. I can use the diff function to find where it changes sign, but then it'll be a little tough to figure out exactly what change has occured, right?

The method does not have to be super fast, as I only have to do this a few times for around 10^5 datapoints.

Upvotes: 1

Views: 4542

Answers (3)

Raab70
Raab70

Reputation: 721

I believe this will do the trick (although it's not very pretty)

a=[1,1,1,1,1,2,2,2,2,1,1,1,2,2,3,3,3];
d=diff(a);
deltas=(d~=0);
d12=[];d23=[];d32=[];d21=[];
last=0;
for i=1:length(a)-1
    if deltas(i)
        if a(i)==1&&a(i+1)==2
            d12=[d12,i-last];
            last=i;
        elseif a(i)==2&&a(i+1)==3
            d23=[d23,i-last];
            last=i;
        elseif a(i)==3&&a(i+1)==2
            d32=[d32,i-last];
            last=i;
        elseif a(i)==2&&a(i+1)==1
            d21=[d21,i-last];
            last=i;
        end

    end
end

Upvotes: 1

dustincarr
dustincarr

Reputation: 1425

This approach will group things the way you specified in the question:

a=[1,1,1,1,2,2,2,1,1,2,2,3,3]
b = diff(a)
c = find(b)
d = diff([0,c]);
type1 = d(b(c) == 1 & a(c) == 1);
type2 = d(b(c) == -1 & a(c) == 2);
type3 = d(b(c) == 1 & a(c) == 2);
type4 = d(b(c) == -1 & a(c) == 3);

type1 =
     4     2
type2 =
     3
type3 =   
     2
type4 =
   Empty matrix: 1-by-0

Upvotes: 3

Luis Mendo
Luis Mendo

Reputation: 112769

Use the standard procedure with diff to detect changes and run lengths, and then apply accumarray to group run lengths according to each pair of values before and after the change:

x = [1,1,1,1,2,2,2,1,1,2,2,3,3];
x = x.'; %'// easier to work with a column vector
ind = find(diff(x))+1; %// index of positions where x changes
%// To detect what change has ocurred, we'll use x(ind-1) and x(ind)
len = diff([1; ind]); %// length of each run
result = accumarray([x(ind-1) x(ind)], len, [], @(v) {v}); %// group lengths

Note the order within each result vector may be altered, as per accumarray.

In your example, this gives

>> result
result = 
     []    [2x1 double]     []
    [3]              []    [2]
>> result{1,2}
ans =
     2
     4
>> result{2,1}
ans =
     3
>> result{2,3}
ans =
     2

Upvotes: 3

Related Questions