我有一个数组的数组,就像这样:

[
    [1,2,3],
    [1,2,3],
    [1,2,3],
]

我想把它转置得到下面的数组:

[
    [1,1,1],
    [2,2,2],
    [3,3,3],
]

用循环来实现这一点并不难:

function transposeArray(array, arrayLength){
    var newArray = [];
    for(var i = 0; i < array.length; i++){
        newArray.push([]);
    };

    for(var i = 0; i < array.length; i++){
        for(var j = 0; j < arrayLength; j++){
            newArray[j].push(array[i][j]);
        };
    };

    return newArray;
}

然而,这看起来很笨重,我觉得应该有更简单的方法来做到这一点。是吗?


当前回答

扩展语法不应该用作push的替代品,它只应该在你不想改变现有数组的时候使用。

算法: 对于每一列,只要检查该列是否在结果矩阵中有一行,如果已经有一行,那么简单地推元素,否则创建一个新的行数组,然后推。

因此,与上面的许多其他解决方案不同,这个解决方案不会一次又一次地创建新数组,而是将相同的数组推入。

另外,花点时间了解Nullish Coalescing Operator的用法。

常量 转置= arr => arr。foreach ((v, i) => (m[i]) ??= [], m[i].push(v))), m), []), 矩阵= [[1,2,3],[1,2,3],[1,2,3]] console.log(转置矩阵)

其他回答

如果使用RamdaJS是一个选项,这可以在一行中实现:

这里有很多好答案!我把它们合并成一个答案,并更新了一些代码以获得更现代的语法:

灵感来自Fawad Ghafoor和Óscar Gómez Alcañiz的俏皮话

function transpose(matrix) {
  return matrix[0].map((col, i) => matrix.map(row => row[i]));
}

function transpose(matrix) {
  return matrix[0].map((col, c) => matrix.map((row, r) => matrix[r][c]));
}

由Andrew Tatomyr设计的函数方法风格

function transpose(matrix) {
  return matrix.reduce((prev, next) => next.map((item, i) =>
    (prev[i] || []).concat(next[i])
  ), []);
}

洛达什/马塞尔的下划线

function tranpose(matrix) {
  return _.zip(...matrix);
}

// Without spread operator.
function transpose(matrix) {
  return _.zip.apply(_, [[1,2,3], [1,2,3], [1,2,3]])
}

Vigrant的更简单的Lodash/Underscore解决方案

_.unzip(matrix);

香草的方法

function transpose(matrix) {
  const rows = matrix.length, cols = matrix[0].length;
  const grid = [];
  for (let j = 0; j < cols; j++) {
    grid[j] = Array(rows);
  }
  for (let i = 0; i < rows; i++) {
    for (let j = 0; j < cols; j++) {
      grid[j][i] = matrix[i][j];
    }
  }
  return grid;
}

由伊曼纽尔·萨林根启发的香草ES6方法

function transpose(matrix) {
  for (var i = 0; i < matrix.length; i++) {
    for (var j = 0; j < i; j++) {
      const temp = matrix[i][j];
      matrix[i][j] = matrix[j][i];
      matrix[j][i] = temp;
    }
  }
}

// Using destructing
function transpose(matrix) {
  for (var i = 0; i < matrix.length; i++) {
    for (var j = 0; j < i; j++) {
      [matrix[i][j], matrix[j][i]] = [matrix[j][i], matrix[i][j]];
    }
  }
}

我发现上面的答案要么很难读懂,要么太啰嗦,所以我自己写了一个。我认为这是在线性代数中实现转置的最直观的方法,你不做值交换,而只是把每个元素插入到新矩阵的正确位置:

function transpose(matrix) {
  const rows = matrix.length
  const cols = matrix[0].length

  let grid = []
  for (let col = 0; col < cols; col++) {
    grid[col] = []
  }
  for (let row = 0; row < rows; row++) {
    for (let col = 0; col < cols; col++) {
      grid[col][row] = matrix[row][col]
    }
  }
  return grid
}

使用lodash/下划线和es6的最短方式:

_.zip(...matrix)

其中矩阵为:

const matrix = [[1,2,3], [1,2,3], [1,2,3]];

另一种方法是从外部到内部迭代数组,并通过映射内部值来减小矩阵。

常量 转置=数组=>数组。Reduce ((r, a) => .map((v, i) =>[…(r[i] || []), v]), []), 矩阵= [[1,2,3],[1,2,3],[1,2,3]]; console.log(转置矩阵(矩阵));