如果这个问题是重复的,或者如果这个问题的解决方案在Matlab中非常简单,请提前道歉。我有一个M × N矩阵A
,一个1 × M向量ind
,和另一个向量val
。例如,
A = zeros(6,5);
ind = [3 4 2 4 2 3];
val = [1 2 3];
我想对以下代码进行矢量化:
for i = 1 : size(A,1)
A(i, ind(i)-1 : ind(i)+1) = val;
end
>> A
A =
0 1 2 3 0
0 0 1 2 3
1 2 3 0 0
0 0 1 2 3
1 2 3 0 0
0 1 2 3 0
也就是说,对于A
的第i行,我想将向量val
插入到某个位置,由ind
的第i项指定。在没有for循环的Matlab中做到这一点的最佳方法是什么?
可以使用 bsxfun
的遮罩功能:构建一个遮罩,告诉值将被放置的位置,然后填充这些值。在这样做时,更容易使用列而不是行(因为Matlab的列主顺序),并在最后转置。
下面的代码决定了最终A
中最小列数,以便所有值都适合指定的位置。
你的例子应用了-1
相对于ind
的位移。代码包含一个泛型位移,可以修改。
%// Data
ind = [3 4 2 4 2 3]; %// indices
val = [1 2 3]; %// values
d = -1; %// displacement for indices. -1 in your example
%// Let's go
n = numel(val);
m = numel(ind);
N = max(ind-1) + n + d; %// number of rows in A (rows before transposition)
mask = bsxfun(@ge, (1:N).', ind+d) & bsxfun(@le, (1:N).', ind+n-1+d); %// build mask
A = zeros(size(mask)); %/// define A with zeros
A(mask) = repmat(val(:), m, 1); %// fill in values as indicated by mask
A = A.'; %// transpose
示例中的结果:
A =
0 1 2 3 0
0 0 1 2 3
1 2 3 0 0
0 0 1 2 3
1 2 3 0 0
0 1 2 3 0
结果与d = 0
(无位移):
A =
0 0 1 2 3 0
0 0 0 1 2 3
0 1 2 3 0 0
0 0 0 1 2 3
0 1 2 3 0 0
0 0 1 2 3 0
如果你能处理一点bsxfun
过量,这里有一个bsxfun's
添加能力 -
N = numel(ind);
A(bsxfun(@plus,N*[-1:1]',(ind-1)*N + [1:N])) = repmat(val(:),1,N)
示例运行-
>> ind
ind =
3 4 2 4 2 3
>> val
val =
1 2 3
>> A = zeros(6,5);
>> N = numel(ind);
>> A(bsxfun(@plus,N*[-1:1]',(ind-1)*N + [1:N])) = repmat(val(:),1,N)
A =
0 1 2 3 0
0 0 1 2 3
1 2 3 0 0
0 0 1 2 3
1 2 3 0 0
0 1 2 3 0