Reputation: 775
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
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
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
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