将矩阵对角线转换为不规则数组?

3

我正在尝试提出以下问题的非暴力解决方案。给定任意大小的矩阵:

[6  0  3  5]
[3  7  1  4]
[1  4  8  2]
[0  2  5  9]

将其对角线转换为向量列表,如下所示:

(0)
(1, 2)
(3, 4, 5)
(6, 7, 8, 9)
(0, 1, 2)
(3, 4)
(5)

在这个例子中,从左下到右上工作,有没有一种优雅的方法来完成这个任务,而不是迭代左列和上行?
3个回答

2
我将编写一个小函数来将向量索引转换为矩阵索引。假设矩阵是N*N的正方形,则会有2N-1个向量;如果我们将向量从0到2N-2编号,向量n的元素k将位于行max(N-1-n+k,k)和列max(n+k-N+1,k)(或者反过来,行i,列j的矩阵元素将是向量N-1+j-i的元素min(i,j))。然后,每当您需要访问向量的元素时,只需将坐标从k,n转换为i,j(即将向量索引转换为矩阵索引),并访问矩阵的相应元素。而不是实际上拥有向量列表,您最终将得到一些模拟向量列表的东西,因为它可以给出列表中任何向量的任何所需元素-这真的很好。(欢迎使用鸭子类型;-))
但是,如果您要访问矩阵的每个元素,可能比每次进行此计算更快地进行迭代。

1

(未经检查的代码) 类似这样(Java 代码):

// suppose m is the matrix, so basically an int[][] array with r rows and c columns
// m is an int[rows][cols];

List result = new ArrayList(rows + cols - 1);
for (int i = 0; i < (rows + cols - 1))
{
  int y;
  int x;
  if (i < rows)
  {
    x = 0;
    y = rows - i - 1;
  }
  else
  {
    x = i - rows + 1;
    y = 0;
  }
  Vector v = new Vector();
  while (y < rows && x < cols)
  {
    y++;
    x++;
    v.add(new Integer(m[y][c]));
  }
  result.add(v);
}
// result now contains the vectors you wanted

编辑:我把x和y搞混了,现在已经更正。


建议:循环内再次使用 ArrayList,而不是 Vector。 (此外,可以更新为使用泛型和自动装箱的现代 Java) - David Z
@David:我会使用ArrayLists,但原始帖子谈到了向量 :) 而且(仍然)不是每个人都使用Java 1.5+。 - tehvan

0

Mathematica:

m = {{6, 0, 3, 5}, 
     {3, 7, 1, 4}, 
     {1, 4, 8, 2}, 
     {0, 2, 5, 9}};

Table[Diagonal[m, i], {i, 1 - Length@m, Length@m[[1]] - 1}]

该函数返回第i条对角线的列表,其中第0条对角线是主对角线,i = -1表示它下面的一条对角线,以此类推。

{{0}, {1, 2}, {3, 4, 5}, {6, 7, 8, 9}, {0, 1, 2}, {3, 4}, {5}}

当然,使用内置的Diagonal函数有点作弊。这里是一个从头开始实现Diagonal的方法:

(* Grab the diagonal starting from element (i,j). *)
diag0[m_,i_,j_] := Table[m[[i+k, j+k]], {k, 0, Min[Length[m]-i, Length@m[[1]]-j]}]

(* The i'th diagonal -- negative means below the main diagonal, positive above. *)
Diagonal[m_, i_] := If[i < 0, diag0[m, 1-i, 1], diag0[m, 1, i+1]]

Table函数基本上是一个for循环,它会将结果收集到一个列表中。例如:

Table[2*i, {i, 1, 5}]

返回{2,4,6,8,10}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接