﻿ matlab – 通过另一个单元格数组的索引对数组求和 - 代码日志

#### matlab – 通过另一个单元格数组的索引对数组求和

a = [109, 894, 566, 453, 342, 25]

subs = { [1,3,4], [2,5,6], [1,3], [3,4], [2,3,4], [6] };

for i=1:6
sums_a(i) = sum(a(subs{i}));
end

idx = cumsum(cellfun('length', subs));
x = diff(bsxfun(@ge, [0; idx(:)], 1:max(idx)));
x = sum(bsxfun(@times, x', 1:numel(subs)), 2);  %'// Produce subscripts
y = a([subs{:}]);                               % // Obtain values
sums_a = accumarray(x, y);                      % // Accumulate values

y = a([subs{:}]);

1    1    1    2    2    2    3    3    4    4    5    5    5    6

>累计y中的前3个值,结果存储为输出中的第一个元素.
>累计接下来的3个值,结果存储为输出中的第二个元素.
>累计接下来的两个值,结果存储为输出中的第三个元素.

idx = cumsum(cellfun('length', subs));
x = diff(bsxfun(@ge, [0; idx(:)], 1:max(idx)));
x = sum(bsxfun(@times, x', 1:numel(subs)), 2);

sums_a = accumarray(x, y);

a = [109,894,566,453,342,25];
subs = {[1,3,4], [2,5,6], [1,3], [3,4], [2,3,4], 6};

% // Solution with arrayfun
tic
for k = 1:1000
clear sums_a1
sums_a1 = cellfun( @(subs) sum( a(subs) ), subs );
end
toc

% // Solution with accumarray
tic
for k = 1:1000
clear sums_a2
idx = cumsum(cellfun('length', subs));
x = diff(bsxfun(@ge, [0; idx(:)], 1:max(idx)));
x = sum(bsxfun(@times, x', 1:numel(subs)), 2);
sums_a2 = accumarray(x, a([subs{:}]));
end
toc

%'// Solution with for loop
tic
for k = 1:1000
clear sums_a3
for n = 1:6
sums_a3(n) = sum(a(subs{n}));
end
end
toc

Elapsed time is 0.027746 seconds.
Elapsed time is 0.004228 seconds.
Elapsed time is 0.001959 seconds.

accumarray与arrayfun的加速几乎是十倍,但请注意for循环仍然比两者都快.