首页 > 解决方案 > 在 JS 中以最干净和最紧凑的方式在所有可能的方向上对角迭代矩阵

问题描述

因此,我正在尝试编写一个函数,该函数可以通过可配置的从左到右或从右到左迭代对角线迭代任何矩阵(方形或非方形),矩阵沿着对角线迭代,从上到下或从下到上迭代。我确实想出了一个函数,它成功地从左到右、从下到上沿任一对角线迭代矩阵

function iterateDiagonally(matrix, main, rightToLeft, topToBottom)
{
  for(let a = 0, b = matrix.length + matrix[0].length - 1; a < b; ++a)
  {
    let x = main ? Math.min(a, matrix.length - 1) : Math.max(0, a - matrix[0].length + 1);
    let y = main ? Math.min(matrix[0].length - 1, matrix.length + 1 - a) : Math.min(a, matrix[0].length - 1);
    for(let c = 0, d = Math.min(y + 1, main ? x + 1 : matrix.length - x); c < d; ++c)
    {
      let eX = main ? x - c : x + c;
      let eY = y - c;
      console.log(matrix[eX][eY]);
    }
  }
}
/*
1 4 7
2 5 8
3 6 9
*/
console.log("Along the main diagonal");
iterateDiagonally([[1, 2, 3], [4, 5, 6], [7, 8, 9]], true);
console.log("Along the antidiagonal");
iterateDiagonally([[1, 2, 3], [4, 5, 6], [7, 8, 9]], false);

但意识到也使前 2 个参数变量会使(已经很庞大的代码)看起来更庞大。因此,我正在寻找一种更干净、更紧凑且效率不低的解决方案。谢谢!

标签: javascriptarraysloopsmatrixiteration

解决方案


所以经过深思熟虑,我最终自己完成了它。如果有人遇到同样的问题,请留在这里。它可能看起来很复杂,但想法真的很简单

function iterateDiagonally(matrix, main, rightToLeft, topToBottom)
{
  // Move along half of the perimeter, excluding the duplicate corner element
  // a - first element of each diagonal
  // b - amount of diagonals in total
  for(let a = 0, b = matrix.length + matrix[0].length - 1; a < b; ++a)
  {
    // For the main diagonal, first move right along the x axis starting with the bottom left element, then move up the y axis
    // For the antidiagonal, first move down the y axis starting with the top left element, then move right along the x axis
    let x = main ? Math.min(a, matrix.length - 1) : Math.max(0, a - matrix[0].length + 1);
    let y = main ? Math.min(matrix[0].length - 1, matrix.length + 1 - a) : Math.min(a, matrix[0].length - 1);
    // Invert the starting position and direction of all movement
    if(rightToLeft) x = matrix.length - 1 - x, y = matrix[0].length - 1 - y;
    let diagonal = [];
    // Move along each diagonal
    // c - element of diagonal
    // d - amount of elements in diagonal in total
    for(let c = 0, d = Math.min(rightToLeft ? matrix[0].length - y : y + 1, main !== rightToLeft ? x + 1 : matrix.length - x); c < d; ++c)
    {
      // Invert the diagonal traversal order
      let iC = topToBottom !== rightToLeft ? d - 1 - c : c;
      // X coordinate of the element
      let eX = main !== rightToLeft ? x - iC : x + iC;
      // Y coordinate of the element
      let eY = rightToLeft ? y + iC : y - iC;
      diagonal.push(matrix[eX][eY]);
    }
    console.log(diagonal.join(", "));
  }
}
/*
1 4 7
2 5 8
3 6 9
*/
console.log("Parallel main diagonal, left to right, bottom to top");
iterateDiagonally([[1, 2, 3], [4, 5, 6], [7, 8, 9]], true, false, false);
console.log("Parallel main diagonal, right to left, bottom to top");
iterateDiagonally([[1, 2, 3], [4, 5, 6], [7, 8, 9]], true, true, false);
console.log("Parallel main diagonal, left to right, top to bottom");
iterateDiagonally([[1, 2, 3], [4, 5, 6], [7, 8, 9]], true, false, true);
console.log("Parallel main diagonal, right to left, top to bottom");
iterateDiagonally([[1, 2, 3], [4, 5, 6], [7, 8, 9]], true, true, true);
console.log("Parallel antidiagonal, left to right, bottom to top");
iterateDiagonally([[1, 2, 3], [4, 5, 6], [7, 8, 9]], false, false, false);
console.log("Parallel antidiagonal, right to left, bottom to top");
iterateDiagonally([[1, 2, 3], [4, 5, 6], [7, 8, 9]], false, true, false);
console.log("Parallel antidiagonal, left to right, top to bottom");
iterateDiagonally([[1, 2, 3], [4, 5, 6], [7, 8, 9]], false, false, true);
console.log("Parallel antidiagonal, right to left, top to bottom");
iterateDiagonally([[1, 2, 3], [4, 5, 6], [7, 8, 9]], false, true, true);


推荐阅读