如何改进此代码,以便在MATLAB中从另一个矩阵替换矩阵的元素?

如何改进此代码,以便在MATLAB中从另一个矩阵替换矩阵的元素?,matlab,matrix,Matlab,Matrix,我有4个大小相同的矩阵: k = [0.5; 1.0; 1.5; 2.0]; l = [2; 4; 6; 8]; m = [1.7; 3.0; 4.5; 6.0]; n = [2.5; 5.0; 7.5; 10.0]; k = [0.5; 1.0; 1.5; 2.0]; l = [2; 4; 6; 8]; m = [1.7; 3.0; 4.5; 6.0]; n = [2.5; 5.0; 7.5; 10.0]; Y = arrayfun(@(i) [k(i), l(i); m(i), n(i)

我有4个大小相同的矩阵:

k = [0.5; 1.0; 1.5; 2.0];
l = [2; 4; 6; 8];
m = [1.7; 3.0; 4.5; 6.0];
n = [2.5; 5.0; 7.5; 10.0];
k = [0.5; 1.0; 1.5; 2.0];
l = [2; 4; 6; 8];
m = [1.7; 3.0; 4.5; 6.0];
n = [2.5; 5.0; 7.5; 10.0];

Y = arrayfun(@(i) [k(i), l(i); m(i), n(i)], 1:4, 'UniformOutput', false);
blkdiag(Y{:})

X = cat(3, [k, m], [l, n]);
blkdiag(squeeze(X(1,:,:)), squeeze(X(2,:,:)), squeeze(X(3,:,:)), squeeze(X(4,:,:)))
我想把每个矩阵中的元素放到零矩阵的对角线上,这样会产生如下结果:

f =  0.5 2.0 0   0   0   0   0   0 
     1.7 2.5 0   0   0   0   0   0
     0   0   1.0 4.0 0   0   0   0  
     0   0   3.0 5.0 0   0   0   0  
     0   0   0   0   1.5 6.0 0   0  
     0   0   0   0   4.5 7.5 0   0  
     0   0   0   0   0   0   2.0 8.0
     0   0   0   0   0   0   6.0 10.0
这就是我想到的:

f = zeros(8,8);
k = [0.5; 1.0; 1.5; 2.0];
l = [2; 4; 6; 8];
m = [1.7; 3.0; 4.5; 6.0];
n = [2.5; 5.0; 7.5; 10.0];

for i = 1:2:8 %odd index number
    for j = 2:2:8 %even index number
        f(i,i) = k(1,i)
        f(i,j) = l(1,i)
        f(j,i) = m(1,i)
        f(j,j) = n(i,1)
    end;
end;
disp(f)
但是结果将元素不放在矩阵的对角
f=0(8,8)
,我总是得到
索引的误差超过矩阵维数。


我能得到一些关于如何修复这段代码的建议吗?

我想你是打算写这篇文章的:

for i = 2:2:8
    f(i-1,i-1) = k(i/2)
    f(i-1,i) = l(i/2)
    f(i,i-1) = m(i/2)
    f(i,i) = n(i/2)
end

虽然必须有更简单的方法来完成同样的事情。例如,查看函数

Cris Luengo的答案比我这里的答案更灵活,读起来也更好,但是如果你要使用MATLAB做大量工作,这可能是你想要学习的东西

(此方法通常性能更好,因为它消除了
for
循环的需要。)

在这里,
f
被用作向量(数组),即使它是8*8矩阵。在Matlab中,可以通过指定行数和列数或线性索引从矩阵中访问单个元素


更多的细节可以在这里找到:(参见线性索引)

对不起,我错过了“一切都在移动”的主题。我以前的回答完全不正确

我仍然会使用blkdiag,您只需要重新分配矩阵:

k = [0.5; 1.0; 1.5; 2.0];
l = [2; 4; 6; 8];
m = [1.7; 3.0; 4.5; 6.0];
n = [2.5; 5.0; 7.5; 10.0];
k = [0.5; 1.0; 1.5; 2.0];
l = [2; 4; 6; 8];
m = [1.7; 3.0; 4.5; 6.0];
n = [2.5; 5.0; 7.5; 10.0];

Y = arrayfun(@(i) [k(i), l(i); m(i), n(i)], 1:4, 'UniformOutput', false);
blkdiag(Y{:})

X = cat(3, [k, m], [l, n]);
blkdiag(squeeze(X(1,:,:)), squeeze(X(2,:,:)), squeeze(X(3,:,:)), squeeze(X(4,:,:)))

另一种选择是先构造对角线和两个非对角线向量,然后使用
diag
创建矩阵,然后将它们相加

%Data
k = [0.5;1.0;1.5;2.0];
l = [2;4;6;8];
m = [1.7;3.0;4.5;6.0];
n = [2.5;5.0;7.5;10.0];

%Construct vectors
diagonal = [1;0].*k.' + [0;1].*n.'; %Diagonal of the matrix
offu = [1;0].*l'; %Upper diagonal
offl = [1;0].*m'; %Lower diagonal

A = diag(diagonal(:)) + diag(offu(1:end-1),1) + diag(offl(1:end-1),-1);    
我不知道它是否比其他答案更快,但我喜欢它对正在发生的事情的透明度


注:为了构造变量
对角线
offu
offl
,我使用隐式展开,这需要Matlab R2016b或更新版本。如果您使用的是较旧的版本,您可以使用
bsxfun

如果您正在寻找compact,那么下面是一个有趣的解决方案,使用和:


与你的问题无关,尽管我仍然想指出这一点
k
l
m
n
是向量(1D数组)。只需指定一个索引即可访问该值,即
k(i)
而不是
k(1,i)
。除此之外@anthony还说:
k(1,i)
是一个列向量,第一个索引是行号,因此超出了范围。试试
k(i,1)
。但这只是学习索引的练习
k(i)
更简单、更地道。
k((i+1)/2)
其他人也一样:)我想我现在明白了,非常感谢你的帮助!我还将签出
blkdiag
函数,使此代码更简单@安东尼:完全正确!我根本没注意写那个,是吗?:)这并没有给出问题中所示的预期结果。。。每个块不是一个向量,而是块中的每个对应元素都来自同一个向量对不起@Wolfie,这是真的。修正了。@Wolfie-true。我之前想更详细地说明这个想法,因此我有
idx_k=1:18:nf等。。。后来我决定简化代码,但没有意识到
nf
也被重新编译。答案修改了。这个很好!我知道人们会对此给出非常简短的答案不知何故,我希望克朗能成为解决方案的一部分,但我不知道如何…@CrisLuengo:检查我的编辑。起初我用的是
kron
,后来改成了
repelem
,因为我觉得效率更高。啊,里面有一个
kron
!令人惊叹的!在某个时候,我必须学会使用它…:p这一个真的很好,效率很高!谢谢你的建议!