在JavaScript中转置2D数组

在JavaScript中转置2D数组,javascript,arrays,matrix,transpose,Javascript,Arrays,Matrix,Transpose,我有一个数组,类似于: [ [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++){

我有一个数组,类似于:

[
    [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;
}
函数transposeArray(数组,数组长度){
var newArray=[];
对于(var i=0;i
然而,这看起来很笨重,我觉得应该有一个更简单的方法来做。有吗

array[0].map((_, colIndex) => array.map(row => row[colIndex]));
map
按顺序为数组中的每个元素调用一次提供的
回调
函数,并根据结果构造一个新数组<代码>回调
仅对具有赋值的数组索引调用;对于已删除或从未赋值的索引,不会调用它

回调
由三个参数调用:元素的值、元素的索引和正在遍历的数组对象

你可以用

函数反转数组(数组、数组宽度、数组高度){
var newArray=[];

对于(x=0;x您可以通过只进行一次传递在适当的位置进行:

function transpose(arr,arrLen) {
  for (var i = 0; i < arrLen; i++) {
    for (var j = 0; j <i; j++) {
      //swap element[i,j] and element[j,i]
      var temp = arr[i][j];
      arr[i][j] = arr[j][i];
      arr[j][i] = temp;
    }
  }
}
函数转置(arr,arrLen){
对于(变量i=0;i对于(var j=0;j,您可以通过使用以下方法在没有循环的情况下实现这一点

它看起来非常优雅,不需要任何依赖项,例如of

缩小

function transpose(m){return zeroFill(m.reduce(function(m,r){return Math.max(m,r.length)},0)).map(function(r,i){return zeroFill(m.length).map(function(c,j){return m[j][i]})})}function zeroFill(n){return new Array(n+1).join("0").split("").map(Number)}

这是我制作的一个演示。请注意缺少循环:-)

//创建一个5行9列矩阵。
var m=坐标矩阵(5,9);
//使矩阵为不规则形状。
m[2]=m[2]。切片(0,5);
m[4].pop();
//转置并打印矩阵。
println(formatMatrix(transpose(m));
函数矩阵(行、列、默认值){
返回抽象矩阵(行、列、函数(r、i){
返回arrayFill(cols,defaultVal);
});
}
函数零矩阵(行、列){
返回抽象矩阵(行、列、函数(r、i){
返回零填充(cols);
});
}
函数坐标矩阵(行、列){
返回抽象矩阵(行、列、函数(r、i){
返回零填充(cols).map(函数(c,j){
返回[i,j];
});
});
}
函数抽象矩阵(行、列、行fn){
返回零填充(行).map(函数(r,i){
返回rowFn(r,i);
});
}
/**矩阵函数*/
函数格式矩阵(矩阵){
返回矩阵.reduce(函数(结果,行){
返回结果+行.join('\t')+'\n';
}, '');
}
函数副本(矩阵){
返回零填充(矩阵长度).map(函数(r,i){
返回zeroFill(getMatrixWidth(matrix)).map(函数(c,j){
返回矩阵[i][j];
});
});
}
函数转置(矩阵){
返回zeroFill(getMatrixWidth(matrix)).map(函数(r,i){
返回零填充(矩阵长度).map(函数(c,j){
返回矩阵[j][i];
});
});
}
函数getMatrixWidth(矩阵){
返回矩阵.reduce(函数(结果,行){
返回Math.max(结果,行长度);
}, 0);
}
/**数组填充函数*/
函数零填充(n){
返回新数组(n+1).join('0').split('').map(Number);
}
函数arrayFill(n,默认值){
返回零填充(n).map(函数(值){
返回defaultValue | |值;
});
}
/**打印功能*/
功能打印(str){
str=Array.isArray(str)?str.join(“”):str;
return document.getElementById('out').innerHTML+=str | |'';
}
函数println(str){
print.call(null,[].slice.call(arguments,0).concat(['
')); }
#输出{
空白:预处理;
}

如果您可以选择使用Ramda JS和ES6语法,那么这里有另一种方法:

const transpose=a=>R.map(c=>R.map(R=>R[c],a),R.keys(a[0]);
console.log(转置)([
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
]))//=>[1,5,9],[2,6,10],[3,7,11],[4,8,12]

lodash的最短路径
/
下划线
es6

_.zip(...matrix)
其中,
矩阵
可以是:

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

以下是我在现代浏览器中的实现(无依赖项):


另一种变体是使用
Array.map
。使用索引可以将矩阵转置为
M!=N

// Get just the first row to iterate columns first
var t = matrix[0].map(function (col, c) {
    // For each column, iterate all rows
    return matrix.map(function (row, r) { 
        return matrix[r][c]; 
    }); 
});
所有转置操作都是先映射元素列,然后按行映射。

ES6 1行如下:

let invert = a => a[0].map((col, c) => a.map((row, r) => a[r][c]))
与Óscar相同,但您更愿意顺时针旋转它:

let rotate = a => a[0].map((col, c) => a.map((row, r) => a[r][c]).reverse())

编辑:这个答案不会转换矩阵,而是旋转矩阵。我没有仔细阅读问题:D

顺时针和逆时针旋转:

    function rotateCounterClockwise(a){
        var n=a.length;
        for (var i=0; i<n/2; i++) {
            for (var j=i; j<n-i-1; j++) {
                var tmp=a[i][j];
                a[i][j]=a[j][n-i-1];
                a[j][n-i-1]=a[n-i-1][n-j-1];
                a[n-i-1][n-j-1]=a[n-j-1][i];
                a[n-j-1][i]=tmp;
            }
        }
        return a;
    }

    function rotateClockwise(a) {
        var n=a.length;
        for (var i=0; i<n/2; i++) {
            for (var j=i; j<n-i-1; j++) {
                var tmp=a[i][j];
                a[i][j]=a[n-j-1][i];
                a[n-j-1][i]=a[n-i-1][n-j-1];
                a[n-i-1][n-j-1]=a[j][n-i-1];
                a[j][n-i-1]=tmp;
            }
        }
        return a;
    }
函数逆时针旋转(a){
var n=a.长度;
对于(var i=0;i干净和纯净:

[[0,1],[2,3],[4,5]].reduce((上一个,下一个)=>next.map((项目,i)=>
(上一个[i]| |[]).concat(下一个[i])
), []); // [[0, 2, 4], [1, 3, 5]]
如果提供空阵列,以前的解决方案可能会导致失败

这是一个函数:

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

console.log(transpose([[0, 1], [2, 3], [4, 5]]));
更新。 使用spread运算符可以编写得更好:

const transpose = matrix => matrix.reduce(
    ($, row) => row.map((_, i) => [...($[i] || []), row[i]]), 
    []
)

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

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
}
函数转置(矩阵){
常量行=矩阵长度
常数cols=矩阵[0]。长度
让网格=[]
for(设col=0;col
很多人都去了
    function rotateCounterClockwise(a){
        var n=a.length;
        for (var i=0; i<n/2; i++) {
            for (var j=i; j<n-i-1; j++) {
                var tmp=a[i][j];
                a[i][j]=a[j][n-i-1];
                a[j][n-i-1]=a[n-i-1][n-j-1];
                a[n-i-1][n-j-1]=a[n-j-1][i];
                a[n-j-1][i]=tmp;
            }
        }
        return a;
    }

    function rotateClockwise(a) {
        var n=a.length;
        for (var i=0; i<n/2; i++) {
            for (var j=i; j<n-i-1; j++) {
                var tmp=a[i][j];
                a[i][j]=a[n-j-1][i];
                a[n-j-1][i]=a[n-i-1][n-j-1];
                a[n-i-1][n-j-1]=a[j][n-i-1];
                a[j][n-i-1]=tmp;
            }
        }
        return a;
    }
function transpose(array) {
    return array.reduce((prev, next) => next.map((item, i) =>
        (prev[i] || []).concat(next[i])
    ), []);
}

console.log(transpose([[0, 1], [2, 3], [4, 5]]));
const transpose = matrix => matrix.reduce(
    ($, row) => row.map((_, i) => [...($[i] || []), row[i]]), 
    []
)
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
}
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]));
}
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]])
}
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;
}
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]];
    }
  }
}
const rotate2dArray = <T>(array2d: T[][]) => {
    const rotated2d: T[][] = []

    return array2d.reduce((acc, array1d, index2d) => {
        array1d.forEach((value, index1d) => {
            if (!acc[index1d]) acc[index1d] = []

            acc[index1d][index2d] = value
        })

        return acc
    }, rotated2d)
}
a[0].map((col, i) => a.map(([...row]) => row[i]))
reverseValues(values) {
        let maxLength = values.reduce((acc, val) => Math.max(val.length, acc), 0);
        return [...Array(maxLength)].map((val, index) => values.map((v) => v[index]));
}
    transposeArray: function (mat) {
        let newMat = [];
        for (let j = 0; j < mat[0].length; j++) {  // j are columns
            let temp = [];
            for (let i = 0; i < mat.length; i++) {  // i are rows
                temp.push(mat[i][j]);  // so temp will be the j(th) column in mat
            }
            newMat.push(temp);  // then just push every column in newMat
        }
        return newMat;
    }