Incrementing one value of a MATLAB array multiple times in one line

10,689

Solution 1

What you want to do can be done using the function ACCUMARRAY, like so:

A = [10 20 30];            %# Starting array
index = [1 2 2 1];         %# Indices for increments
increment = [20 10 10 3];  %# Value of increments
A = accumarray([1:numel(A) index].',[A increment]);  %'# Accumulate starting
                                                      %#   values and increments

And the output of this example should be:

A = [33 40 30];


EDIT: If A is a large array of values, and there are just a few increments to add, the following may be more computationally efficient than the above:

B = accumarray(index.',increment);  %'# Accumulate the increments
nzIndex = (B ~= 0);               %# Find the indices of the non-zero increments
A(nzIndex) = A(nzIndex)+B(nzIndex);  %# Add the non-zero increments

Solution 2

Maybe there's something I don't quite get here, but you're basically trying to add 23 to the first element of A, right? So you can write:

A([1, 1]) = A([1, 1]) + sum([20 3])

Also, if you have an index array, you can write

indexArray = [1 2 2 3 1 1 2 1];
toAdd = [20 3];
A = [10 20 30];

A(indexArray) + sum(toAdd)

ans =
33    43    43    53    33    33    43    33
Share:
10,689
Bill Cheatham
Author by

Bill Cheatham

Computer vision, graphics and machine learning.

Updated on June 24, 2022

Comments

  • Bill Cheatham
    Bill Cheatham almost 2 years

    This is a question about incrementing one value of a MATLAB array multiple times in the same statement, without having to use a for loop.

    I set my array as:

    >> A = [10 20 30];
    

    And then run:

    >> A([1, 1]) = A([1, 1]) + [20 3]
    
    A =
    
        13    20    30
    

    Clearly the 20 is ignored. However, i would like it to be included, so that:

    >> A = [10 20 30];
    >> A([1, 1]) = A([1, 1]) + [20, 3]
    

    would give:

    A =
    
        33    20    30
    

    Is there a function to allow this to be done in a nice, vectorised fashion?

    (In reality, the indexing to the array would include multiple indexes, so it could be [1 1 2 2 1 1 1 1 3 3 3] etc., with an array of numbers to increment by (the [20, 3] above) of the same length.)

  • Jonas
    Jonas over 13 years
    @Oli Charlesworth: Not sure whether it does now, but I've edited the question right while you were writing the comment.
  • Oliver Charlesworth
    Oliver Charlesworth over 13 years
    I think the general case has toAdd the same length as indexArray. So if the contents of indexArray were unique, you'd just do A(indexArray) + toAdd.
  • Jonas
    Jonas over 13 years
    @Oli Charlesworth: Ah, ok. Yes, that would make sense as well. I'll update my answer with your comment when it becomes clear that this is what the OP wanted, rather than what @gnovice suggests.
  • Bill Cheatham
    Bill Cheatham over 13 years
    Thanks, I've got that first one working a treat. I believe there's a transpose symbol missing on the SUBS though - I could only make A = accumarray([1:numel(A) index]',[A increment]); work. I'll do some speed comparisons for the second suggestion once my data's populated.
  • gnovice
    gnovice over 13 years
    @Bill: You're right. I forgot that the first input has to be a column vector in this case. In general, the first input has to be an M-by-N matrix where M is the number of values being accumulated and N is the number of subscripts (1 in this case, but more for multidimensional indexing).
  • Jonas
    Jonas over 13 years
    @Adrien: Don't be surprised. @gnovice is the only user with a golden Matlab badge. That means that he's both fast and right.
  • gnovice
    gnovice over 13 years
    @Jonas: ... or thoroughly addicted to SO. ;)