2016-05-31 8 views
4

同じサイズの2つの(大きな)ベクトルa=[0 0 0 0 0]b=[1 2 3 4 5]と、{1、...、length(a)}の値を持つインデックスベクトルind=[1 5 2 1]があります。私は多重度を含めaからindで宣言さbのこれらのエントリを追加したい、あるサブアレイのベクトル化加算

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

を計算したいと思います。

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

はもちろん、はるかに高速ですが、複数回表示されるインデックスは無視されます。

上記のコードを高速化するにはどうすればよいですか?

+0

複数回表示されるインデックスの予想される動作は何ですか?このインデックスの追加を1回だけ実行したいですか? – drorco

+0

いいえ、表示される頻度でインデックスを追加したいと思います。上記forループのように。 – Julian

+0

私はなぜ(ind)+ b(ind)が複数回出現するインデックスを無視するのか分かりません。 – GameOfThrows

答えて

5

uniqueを使用して一意のインデックス値を特定し、3番目の出力を使用してindのどの要素が同じインデックスを共有しているかを判断できます。 accumarrayを使用して、同じインデックスを共有するbのすべての要素を合計することができます。これらの場所に元の値のaを追加します。

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

accumarrayは、単にindで欠落しているエントリの0を返しますので、max(inds) == numel(a)が、これは次のように単純化することができれば。

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]); 
入力がで同じインデックスに対応する第二の入力の値を集約するように、2つの列ベクトルと

accumarray仕組み

最初。ここでは3番目の入力を使用して、結果が同じ場合はaというサイズになり、必要に応じて0が埋められます。

+1

偉大な点、私は常に3番目の入力について忘れてしまった! – Suever