如何获得矩阵的对角线并将它们连接起来?

时间:2010-11-29 03:22:19

标签: matlab matrix concatenation diagonal

短版

如何在MATLAB中执行concatMap?我正在尝试从一系列较小的,不同大小的矢量构建单个矢量。我知道我能做到:

result = [];
for i=1:N
    result = [result nextPart(i)];
end

但这会产生严重的速度影响,必须有更明智的方法concatMap


长版

我正在尝试编写一个MATLAB函数,它返回一个块的反对角线。例如,如果你有块:

1 2 4
3 5 7
6 8 9

然后counterDiagonals(block)应该返回[1 2 3 4 5 6 7 8 9]

我有一个函数可以找到一个块的单个对角线。即counterDiagonal(x, 3)将返回[4 5 6]

因此,counterDiagonals应该与concatMap counterDiagonal(x, i) (1:N) N (2*length(block)-1)一样简单。我怎样才能以有效的方式在MATLAB中做到这一点?

3 个答案:

答案 0 :(得分:4)

接受答案的一个问题是:如果矩阵A有零,它们将被错误地从结果中删除..相反,你应该处理元素的索引:

A = [0 2 4; 3 5 7; 6 8 9];               %# Sample matrix (contains zeros)

ind = reshape(1:numel(A), size(A));      %# indices of elements
ind = fliplr( spdiags( fliplr(ind) ) );  %# get the anti-diagonals (or use ROT90)
ind(ind==0) = [];                        %# keep non-zero indices
result = A(ind);                         %# get elements in desired order

这与前一个问题中给出的this answer非常相似(不同之处在于反数字的反向顺序)。

答案 1 :(得分:3)

我相信你想要做的事情可以使用ROT90SPDIAGS函数完成:

A = [1 2 4; 3 5 7; 6 8 9];  %# Sample matrix
result = rot90(A);          %# Rotate the matrix counter-clockwise
result = spdiags(result);   %# Find all the diagonals
result = result(result ~= 0).';  %'# Remove zero padding and format the results
                                  %#   into a row vector

你最终应该使用result = [1 2 3 4 5 6 7 8 9]

编辑:正如Amro在评论中提到的,上面的代码假定原始矩阵A中没有零。如果原始矩阵中有零,则一种解决方案是使用您知道未出现在原始矩阵中的非零标志值替换它们(例如,NaN),运行上面的代码,然后替换结果中的标志值:

A = [0 2 4; 3 0 7; 6 8 0];  %# Sample matrix
result = rot90(A);          %# Rotate the matrix counter-clockwise
result(result == 0) = nan;  %# Replace zeroes with NaN
result = spdiags(result);   %# Find all the diagonals
result = result(result ~= 0).';  %'# Remove zero padding and format the results
                                  %#   into a row vector
result(isnan(result)) = 0;  %# Put the original zeroes back

答案 2 :(得分:1)

简短版本:

如果你预先分配你的result阵列,一切都会快得多。

result = zeros(1,knownLengthOfResultsArray); %# such as "numel(block)"
ct = 1;
for i=1:N
    tmp = nextPart(i);
    nTmp = length(tmp);
    result(ct:ct+nTmp-1) = tmp;
    ct = ct + nTmp;
end

长版:

但是,重写算法可能更有效。参见例如this question的答案(首先在数组上使用fliplr)或@gnovice's answer