2016-05-31 6 views
4

Предположим, у меня есть два (больших) вектора a=[0 0 0 0 0] и b=[1 2 3 4 5] того же размера и один индексный вектор ind=[1 5 2 1] со значениями в {1, ..., length (a)}. Я хотел бы, чтобы вычислитьВекторизация добавления подмассива

for k = 1:length(ind) 
    a(ind(k)) = a(ind(k)) + b(ind(k)); 
end 
% a = [2 2 0 0 5] 

То есть, я хочу, чтобы добавить эти записи из b объявленных в ind к a включая кратность.

a(ind)=a(ind)+b(ind); 
% a = [1 2 0 0 5] 

намного быстрее, конечно, но игнорирует индексы, которые появляются несколько раз.

Как я могу ускорить выполнение вышеуказанного кода?

+0

Какое ожидаемое поведение для индекса появляется несколько раз? хотите ли вы добавить дополнение к этому индексу только один раз? – drorco

+0

Нет, я бы хотел добавить индекс так часто, как он появляется. Точно так же, как в for-loop выше. – Julian

+0

Я не понимаю, почему индексы (ind) + b (ind) игнорируют индексы, которые появляются несколько раз. – GameOfThrows

ответ

5

Мы можем использовать unique для определения уникальных значений индекса и использования третьего выхода для определения того, какие элементы ind используют один и тот же индекс. Затем мы можем использовать accumarray, чтобы суммировать все элементы b, которые имеют один и тот же индекс. Затем мы добавим их в исходное значение a в этих местах.

[uniqueinds, ~, inds] = unique(ind); 
a(uniqueinds) = a(uniqueinds) + accumarray(inds, b(ind)).'; 

Если max(inds) == numel(a) то это может быть упрощен следующим так accumarray просто вернет 0 для любой отсутствующей записи в ind.

a(:) = a(:) + accumarray(ind(:), b(ind)); 
+0

Результат, который я ожидаю, будет '' [13 12 9] ''. – Julian

+0

@Julian Извините. обновлено. – Suever

+0

Это все еще дает '' [15 14 9] '', я думаю. – Julian

3

Другой подход, основанный на accumarray:

a(:) = a(:) + accumarray(ind(:), b(ind(:)), [numel(a) 1]); 

Как это работает

accumarray с двумя векторами столбцов в качестве входных данных агрегирует значения второго входа, соответствующие одному и тому же индексу в первый. Третий вход используется здесь, чтобы заставить результат быть того же размера, что и a, заполняя нулями при необходимости.

+1

Отличный момент, я всегда забываю о третьем вводе! – Suever