2

I have an array of binary data with long stretches of ones and zeros and I want to find the indices of when it changes.

a = [ 1 1 1 1 1 0 0 0 0 0 0 1 1]

I want to search for [1 0] and [0 1] to find the transition points. I'd like to avoid long loops to find these if possible. Any ideas?

1
  • 3
    You most certainly want to use the diff function. Commented May 21, 2015 at 13:00

3 Answers 3

6

Something like this should do the job:

b = diff(a);                     % (assuming 'a' is a vector)
oneFromZero = find(b ==  1) + 1; % vector of indices of a '1' preceded by a '0'
zeroFromOne = find(b == -1) + 1; % vector of indices of a '0' preceded by a '1'

Depending on what you want exactly, you may or may not want to add 1 to the resulting arrays of indices.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for responding so quickly! This worked beautifully :)
2

I'd go with

d = a(1:end-1) - a(2:end);
ind = find(d);

Here, d will be 1 where you have a ... 1 0 ... in your bit string and it will be -1 where you have a ... 0 1 .... All the other elements in d will be 0, since, at those positions, the bits are equal to their neighbour.

With this in place, you can use find to get the indices where these two patterns occur. The whole procedure is of O(n) complexity, where n=length(a), since it requires two passes through a.

For a = [ 1 1 1 1 1 0 0 0 0 0 0 1 1] the above code computes ind = [5 11].

2 Comments

d = a(1:end-1) - a(2:end); can be simplified to d = -diff(a);.
Is there any performance/speed difference between these two options?
2

To search for an arbitrary pattern of zeros and ones:

  1. You can compute a convolution (conv) of the two sequences in bipolar (±1) form and then find the maxima. Since the convolution flips one of the inputs, it has to be flipped to undo that:

    a = [ 1 1 1 1 1 0 0 0 0 0 0 1 1];
    pattern = [0 1 1];
    result = find(conv(2*a-1, 2*pattern(end:-1:1)-1, 'valid')==numel(pattern));
    

    In this example

    result =
        11
    

    which means that [0 1 1] appears in a only once, namely at index 11.

  2. A simpler approach is to use strfind, exploiting the undocumented fact that this function can be applied to numeric vectors:

    result = strfind(a, pattern);
    

5 Comments

Thank you for answering, I'll keep this in mind in case I need to find a longer pattern.
I haven't run any benchmark, but I would guess your approach using conv is more efficient than mine.
@Jubobs I doubt it. For the specific OP case ([1 0 ] and [0 1]) diff should be very fast
I went with diff because I'm just looking for changes in long sequences of ones and zeros (array of valid flags), but this looks like a great option for finding other patterns. Thanks again
@ErinGoBragh Welcome! That would have been my preferred approach too, for your specific case

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.