Search code examples
matlabvectormodular-arithmetic

Using modualr arithmetic for vector indices in matlab


I have a vector n values and i want to split it into groups n groups of 3 adjacent values if it is considered to have a ring topology.

what i am trying to do is this:

vector = [some values];
groups = {};

for i = 1:size(vector)(2)
    groups{i} = [vector(mod(i-1, size(vector)(2));
                 vector(i);
                 vector(mod(i+1, size(vector)(2))];
endfor

so if n = 10 and i = 1, groups should be [vector(10); vector(1); vector(2)]

it would be pretty straightforward in most programming languages to just use the mod operator, but i am having trouble working out how to do this using matlab as it doesnt use 0 as the initial index of a vector, so if i = 1, then mod(i-1) = 0 which is an illegal index value. Also i = n would be a problem as mod(n, n) = 0.

i have worked out a pretty hack-ish solution in:

vector = [some values];
groups = {};

for i = 1:size(vector)(2)
    if i == 1
        groups{i} = [vector(size(vector)(2));
                     vector(1);
                     vector(2)];
    elseif i == size(vector)(2)
        groups{i} = [vector(size(vector)(2)-1);
                     vector(size(vector)(2);
                     vector(1)];
    else
        groups{i} = [vector(i-1);
                     vector(i);
                     vector(i+1)];
    endif
endfor

but it is pretty inelegant and i feel like there should be a better way to do it..

is there some operator that allows you to perform modular arithmetic over vector indexes?


Solution

  • Indeed, the 1-based indexing method of matlab can be quite irritating sometimes...
    You can simply add 1 to your 0-based indices, though

    n = numel(vector);
    for ii = 1:n
        idx0 = mod( ii + [-2, 1, 0], n ); % 0-based indices
        group{ii} = vector( idx0 + 1 );
    end
    

    Now, good Matlab practices are about , here's one way to vectorize this for-loop

    idx0 = mod( bsxfun( @plus, 1:n, [-2;1;0] ), n ); % all indices at once
    group = mat2cell( vector( idx0+1 ).', ones(n,1), 3 );
    

    You can lookup mat2cell in mathworks web site for more information. You can also read about here at SO for more examples and information.


    PS,
    It is best not to use i as a variable name in Matlab.