基于Matlab的二维数组索引
我有一个2D矩阵,比如M=0(10,10) 我有另一个列矩阵,V=[1;2;3;4;5;6;5;4;3;2] 我希望能够为所有j>=V(I)设置M(I,j)=1 我知道我可以循环完成这项工作基于Matlab的二维数组索引,matlab,matrix,indexing,2d,Matlab,Matrix,Indexing,2d,我有一个2D矩阵,比如M=0(10,10) 我有另一个列矩阵,V=[1;2;3;4;5;6;5;4;3;2] 我希望能够为所有j>=V(I)设置M(I,j)=1 我知道我可以循环完成这项工作 for i=1:10 M(i,V(i):10) = 1; end 但似乎可以使用某种形式的Matlab索引来避免使用循环。例如: M(:,V:10)=1; 或 但这两者都没有产生预期的结果 我是否可以使用一些语法糖分来实现这一点,或者我应该恢复循环?这几乎不微妙,也不比循环好,我不认为,但是: [
for i=1:10
M(i,V(i):10) = 1;
end
但似乎可以使用某种形式的Matlab索引来避免使用循环。例如:
M(:,V:10)=1;
或
但这两者都没有产生预期的结果
我是否可以使用一些语法糖分来实现这一点,或者我应该恢复循环?这几乎不微妙,也不比循环好,我不认为,但是:
[J,I] = meshgrid(1:10,1:10);
V = [1;2;3;4;5;6;5;4;3;2];
M = J>V(I);
享受吧。这并不微妙,也不比循环好,我不认为,但是:
[J,I] = meshgrid(1:10,1:10);
V = [1;2;3;4;5;6;5;4;3;2];
M = J>V(I);
享受。试试这个:
v = [1;2;3;4;5;6;5;4;3;2];
n = 10;
M = repmat((1:n)', 1, numel(v)) > repmat(v', n, 1);
试试这个:
v = [1;2;3;4;5;6;5;4;3;2];
n = 10;
M = repmat((1:n)', 1, numel(v)) > repmat(v', n, 1);
我尝试了循环方法和“网格网格”方法。我想知道计算大型矩阵的时间(因为matlab中循环的问题通常是时间) 首先,我优化了代码,使其如下所示:
V = V*ones(1,n);
N = ones(1,n)'*(1:n);
M = N>=V;
事实上,N是一个网格,但这样做似乎要快得多
我试过这个:
n = 10000;
V = randi(n-1,1,n)';
tic;
M = zeros(n);
for i=1:n
M(i,V(i):n) = 1;
end
toc
tic;
[J,I] = meshgrid(1:n,1:n);
M = J>=V(I);
toc
tic;
V = V*ones(1,n);
N = ones(1,n)'*(1:n);
M = N>=V;
toc
结果是:
Elapsed time is 1.726872 seconds.
Elapsed time is 5.206657 seconds.
Elapsed time is 1.548600 seconds.
但是使用矩阵而不是循环的方法对于大的n来说会消耗内存。我会坚持循环。我尝试了循环方法和“网格网格”方法。我想知道计算大型矩阵的时间(因为matlab中循环的问题通常是时间) 首先,我优化了代码,使其如下所示:
V = V*ones(1,n);
N = ones(1,n)'*(1:n);
M = N>=V;
事实上,N是一个网格,但这样做似乎要快得多
我试过这个:
n = 10000;
V = randi(n-1,1,n)';
tic;
M = zeros(n);
for i=1:n
M(i,V(i):n) = 1;
end
toc
tic;
[J,I] = meshgrid(1:n,1:n);
M = J>=V(I);
toc
tic;
V = V*ones(1,n);
N = ones(1,n)'*(1:n);
M = N>=V;
toc
结果是:
Elapsed time is 1.726872 seconds.
Elapsed time is 5.206657 seconds.
Elapsed time is 1.548600 seconds.
但是使用矩阵而不是循环的方法对于大的n来说会消耗内存。我个人会坚持循环。既然你在寻找语法上的糖分,这里有一种深奥的方法 假设
V
的长度是所需矩阵M
中两个维度的大小,首先创建一个相同大小的单位矩阵,然后适当索引并取cumsum
:
V = [1;2;3;4;5;6;5;4;3;2]; #% 10x1 vector
E = eye(length(V), length(V)); #%10x10 identity matrix
M = cumsum(E(V,:),2)
M =
1 1 1 1 1 1 1 1 1 1
0 1 1 1 1 1 1 1 1 1
0 0 1 1 1 1 1 1 1 1
0 0 0 1 1 1 1 1 1 1
0 0 0 0 1 1 1 1 1 1
0 0 0 0 0 1 1 1 1 1
0 0 0 0 1 1 1 1 1 1
0 0 0 1 1 1 1 1 1 1
0 0 1 1 1 1 1 1 1 1
0 1 1 1 1 1 1 1 1 1
好的,现在:没有那么有趣,但是(在我的机器上)比迄今为止测试过的任何其他选项都要快:
n=10000;
V = randi(n-1, 1, n); #% as in @KevinRatelle's answer (but not transposed)
tic;
Vlinear = reshape(V + (0:n-1)*n, 1, []); #% find linear indices of first "ones"
M = zeros(n);
M(Vlinear)=1;
M=cumsum(M);
toc
既然你在寻找语法上的甜点,这里有一种深奥的方法 假设
V
的长度是所需矩阵M
中两个维度的大小,首先创建一个相同大小的单位矩阵,然后适当索引并取cumsum
:
V = [1;2;3;4;5;6;5;4;3;2]; #% 10x1 vector
E = eye(length(V), length(V)); #%10x10 identity matrix
M = cumsum(E(V,:),2)
M =
1 1 1 1 1 1 1 1 1 1
0 1 1 1 1 1 1 1 1 1
0 0 1 1 1 1 1 1 1 1
0 0 0 1 1 1 1 1 1 1
0 0 0 0 1 1 1 1 1 1
0 0 0 0 0 1 1 1 1 1
0 0 0 0 1 1 1 1 1 1
0 0 0 1 1 1 1 1 1 1
0 0 1 1 1 1 1 1 1 1
0 1 1 1 1 1 1 1 1 1
好的,现在:没有那么有趣,但是(在我的机器上)比迄今为止测试过的任何其他选项都要快:
n=10000;
V = randi(n-1, 1, n); #% as in @KevinRatelle's answer (but not transposed)
tic;
Vlinear = reshape(V + (0:n-1)*n, 1, []); #% find linear indices of first "ones"
M = zeros(n);
M(Vlinear)=1;
M=cumsum(M);
toc
我添加了两个选项,包括一个使用线性索引和累积和非常快(比这些更快)的选项。如果您想直接针对这些进行速度测试,我很想知道它的运行情况。另外,在非循环测试中,请注意,
M
将是一个逻辑矩阵,除非您将其转换为双精度,否则会使它们变慢。尝试了您的方法(使用cumsum),对于N=10000,需要0.852秒,使您的方法成为所有方法中最快的,大约是loop one速度的两倍我添加了两个选项,包括一个使用线性索引和cumsum的非常快(比这些快)的选项。如果您想直接针对这些进行速度测试,我很想知道它的运行情况。另外,在非循环测试中,请注意,M
将是一个逻辑矩阵,除非您将其转换为双精度,否则会使它们变慢。尝试了您的方法(使用cumsum),对于N=10000,需要0.852秒,使您的方法成为所有方法中最快的,速度大约是loop One的两倍,在风格和独创性方面有许多优点。感谢大家的回答,这是一次有益的学习经历。我将学会并行思考…许多关于风格和创造力的观点。感谢大家的回答,这是一次有益的学习经历。我将学会并行思考。。。