向量化子数组的加法

Vectorizing addition of subarray

假设我有两个大小相同的(大)向量 a=[0 0 0 0 0]b=[1 2 3 4 5] 以及一个索引向量 ind=[1 5 2 1],其值在 {1,...,length(一种)}。我想计算

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

也就是说,我想将ind中声明的b的条目添加到a中,包括多重性。

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

当然要快得多,但会忽略出现多次的索引。

我怎样才能加快上面的代码?

我们可以使用 unique 来识别唯一索引值,并使用第三个输出来确定 ind 的哪些元素共享相同的索引。然后我们可以使用 accumarray 对共享相同索引的 b 的所有元素求和。然后我们将这些添加到这些位置的 a 的原始值。

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

如果 max(inds) == numel(a) 那么这可以简化为以下内容,因为 accumarray 将简单地 return 0 对于 ind 中的任何缺失条目。

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

基于accumarray的另一种方法:

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

工作原理

accumarray 以两个列向量作为输入聚合对应于第一个相同索引的第二个输入的值。第三个输入在这里用于强制结果与 a 大小相同,如果需要用零填充。