【问题标题】:Create new matrix based on diagonal and antidiagonal of given matrix根据给定矩阵的对角线和反对角线创建新矩阵
【发布时间】:2019-05-21 00:53:00
【问题描述】:

我想从矩阵A 创建矩阵B,规则如下:

  • 非对角元素A 类似于B 的非对角元素。

  • A 的主对角线是B 的对角线

  • A 的对角线是B 的主对角线。

例如:

A = [ 1  2  3  4;
      7  8  9 10;
     13 14 15 16; 
     19 20 21 22 ];
B = [ 4  2  3  1;
      7  9  8 10;
     13 15 14 16;
     22 20 21 19 ];

如果给定A,我如何创建B

【问题讨论】:

    标签: matlab matrix


    【解决方案1】:

    您可以创建所有索引,然后它是一个单一的分配。

    % Get size of square matrix A
    n = size(A,1);
    % Indicies are 1:n^2 by default
    idx = 1:n^2;
    % Swap diagonal and antidiagonal indices
    idx( [1:(n+1):n^2, n^2-n+1:1-n:n] ) = [n^2-n+1:1-n:n, 1:(n+1):n^2];
    % Use the indexing array to create B from A, reshape to be n*n
    B = reshape( A( idx ), n, n );
    

    您的示例的输出 A:

    B =
         4     2     3     1
         7     9     8    10
        13    15    14    16
        22    20    21    19
    

    【讨论】:

    • 一口气完成所有索引...不错!
    • @Hoki 认为一定有办法!
    【解决方案2】:

    有很多方法可以达到这个结果,这只是一个索引练习。对于大小为 n 的任何 square 矩阵,这是达到该结果的一种(众多)方法:

    %% input
    A=[ 1  2  3  4 ;
        7  8  9 10 ;
       13 14 15 16 ;
       19 20 21 22 ];
    
    %% Calculate linear indices for the diagonal and antidiagonal
    n=size(A,1) ;                   
    idxdiag     = 1:(n+1):n^2 ;     % => idxdiag     = [1 6 11 16]
    idxantidiag = n:(n-1):n^2-1 ;   % => idxantidiag = [4 7 10 13]
    
    %% Generate B
    B = A ;            % start with a simple copy (for the non-diagonal elements)
    
    % Method 1: direct indice assignment
    B(idxdiag)     = diag(fliplr(A)) ;  % Assign diagonal elements of B
    B(idxantidiag) = flipud(diag(A)) ;  % Assign antidiagonal elements of B
    
    % Method 2: summation
    B([idxdiag idxantidiag]) = 0 ;
    B = B + diag(diag(fliplr(A))) + fliplr(diag(diag(A))) ;
    
    B =
         4     2     3     1
         7     9     8    10
        13    15    14    16
        22    20    21    19
    

    两种方法都返回完全相同的矩阵B


    我建议您熟悉用于了解幕后情况的 MATLAB 函数:

    并且可以在以下位置阅读: Matrix Indexing in MATLAB

    【讨论】:

    • 非常感谢您的回答和链接。我没有关于 Fliplr 和 Flipud 的信息。再次感谢。
    【解决方案3】:

    我的想法有点不同,得出了一个结论

    A=[1 2 3 4;7 8 9 10;13 14 15 16; 19 20 21 22];;
    n=size(A,1) ;
    B=zeros(n,n) ;
    
    for i=1:n
        for j=1:n
            if i==j
                B(i,j)=A(i,n-i+1);
            elseif j==n-i+1
                B(i,j)=A(i,i);
            else
                B(i,j)=A(i,j);
            end
        end 
    end
    B
    

    【讨论】:

    • 当你需要做一些事情时,使用简单的循环总是好的。如果您想在 MATLAB 中很好地运行,您通常会发现使用矢量化要快得多!我的解决方案和 Hoki 的解决方案都是矢量化的,并且可能更快 - 如果您的实际应用程序只有 4*4 矩阵,这不是问题。
    • @ Wolfie,谢谢。没错,你的回答很有效率,我使用它们。但我不熟悉这样的命令。我可以阅读和熟悉这些命令的最佳来源是什么?
    • 循环没有问题。 10 年前,这个循环会比相应的矢量化代码慢 100 或 1000 倍,现在它可能只慢 5 或 10 倍。这通常没什么大不了的。如果您发现代码对于您的需求来说太慢了,那就是寻找向量化方法的时候了。 -- 学习所有存在的功能以及如何有效地使用它们是经验带来的。经常来这里,阅读问题和答案,应用所学,然后一点一点变得更容易和容易。
    • 我完全同意@Cris,我不是故意放下你的答案——很高兴你自己解决了!我的评论的重点应该是 当你需要做某事时使用简单的循环总是好的 :)
    【解决方案4】:

    这是使用eyefindflip 生成linear indices 的变体:

    ind1 = find(eye(size(A)));
    ind2 = flip(find(flip(eye(size(A)))));
    B = A;
    B([ind1 ind2]) = B([ind2 ind1]);
    
    B =
    
         4     2     3     1
         7     9     8    10
        13    15    14    16
        22    20    21    19
    

    这是上面的一个变体,它只使用eyeflip 来生成logical indices

    ind1 = eye(size(A), 'logical');
    ind2 = flip(ind1);
    B = A;
    B(ind1) = flip(A(ind2));
    B(ind2) = flip(A(ind1));
    
    B =
    
         4     2     3     1
         7     9     8    10
        13    15    14    16
        22    20    21    19
    

    【讨论】:

      猜你喜欢
      • 2015-11-13
      • 1970-01-01
      • 1970-01-01
      • 2016-02-10
      • 2018-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多