Bowecho
Bowecho

Reputation: 909

Count lengths of sequences of consecutive integers in MATLAB

I want to count all lengths of sequences of consecutive integers and return those as a vector. For example, consider the vector: x = [1 2 3 4 6 8 9 10 12 13];

The lengths will be:

length([1 2 3 4]) = 4;
length([6]) = 1;
length([8 9 10]) = 3;
length([12 13]) = 2;  

So, the result I want to generate is:

y = [4 1 3 2] 

How can I achieve this?

Upvotes: 0

Views: 1052

Answers (4)

Luis Mendo
Luis Mendo

Reputation: 112659

A small variation of A. Donda's answer:

  1. Use diff to detect differences larger than 1. This gives a 1 value at the end of each run.
  2. Accumulate backwards (with cumsum) to assign a different numeric label to each run. Accumulation is done backwards because the 1 values in step 1 are at the end of each run, not at the beginning.
  3. Compute run length with histc.

Code:

y = [diff(x)>1 1];               %// step 1
y = cumsum(fliplr(y));           %// step 2
y = fliplr(histc(y, 1:y(end)));  %// step 3

Upvotes: 2

knedlsepp
knedlsepp

Reputation: 6084

This is equal to the run lengths of x - (1:length(x)). Therefore you could use:

runLengths = @(x) diff([0, reshape(find(x(1:end-1)~=x(2:end)),1,[]), numel(x)]);
sequenceCounts = @(x) runLengths(x(:)-(1:numel(x)).');
result = sequenceCounts(x);

Upvotes: 1

A. Donda
A. Donda

Reputation: 8467

This should do the trick:

y = diff(find(diff([nan ; x(:) ; nan]) ~= 1))

The inner diff looks for steps that are not +1 (sequence breaks), the find determines the corresponding positions (indices), the outer diff computes sequence lengths as differences between sequence break positions. The nans are there to make sure that the sequence at the beginning and the sequence at the end of the vector are found, by inducing diff values different from 1.

Upvotes: 3

mwengler
mwengler

Reputation: 2778

x = [1 2 3 4 6 8 9 10 12 13];

consecs = []; % empty vector to store answers
consec = 1; % initialize
for I=2:length(x)
    if x(I)==x(I-1)+1 % this one is consecutive with previous
        consec = consec+1;
    else % this one starts a new set of consecutives
        consecs(end+1) =  consec;
        consec = 1;
    end
end
consecs(end+1)=consec; % remember to include the last consecutives
display(consecs)

This is tested and it works.

Upvotes: 0

Related Questions