Transposing a 2D-array in JavaScript

后端 未结 23 2904
难免孤独
难免孤独 2020-11-22 01:40

I\'ve got an array of arrays, something like:

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

I would like to transpose it to get the following

相关标签:
23条回答
  • 2020-11-22 02:14
    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]));
    }
    
    0 讨论(0)
  • 2020-11-22 02:16

    You could use underscore.js

    _.zip.apply(_, [[1,2,3], [1,2,3], [1,2,3]])
    
    0 讨论(0)
  • 2020-11-22 02:17
    function invertArray(array,arrayWidth,arrayHeight) {
      var newArray = [];
      for (x=0;x<arrayWidth;x++) {
        newArray[x] = [];
        for (y=0;y<arrayHeight;y++) {
            newArray[x][y] = array[y][x];
        }
      }
      return newArray;
    }
    
    0 讨论(0)
  • 2020-11-22 02:20

    ES6 1liners as :

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

    so same as Óscar's, but as would you rather rotate it clockwise :

    let rotate = a => a[0].map((col, c) => a.map((row, r) => a[r][c]).reverse())
    
    0 讨论(0)
  • 2020-11-22 02:22

    You can achieve this without loops by using the following.

    • Array
    • Array.prototype.map
    • Array.prototype.reduce
    • Array.prototype.join
    • String.prototype.split

    It looks very elegant and it does not require any dependencies such as jQuery of Underscore.js.

    function transpose(matrix) {  
        return zeroFill(getMatrixWidth(matrix)).map(function(r, i) {
            return zeroFill(matrix.length).map(function(c, j) {
                return matrix[j][i];
            });
        });
    }
    
    function getMatrixWidth(matrix) {
        return matrix.reduce(function (result, row) {
            return Math.max(result, row.length);
        }, 0);
    }
    
    function zeroFill(n) {
        return new Array(n+1).join('0').split('').map(Number);
    }
    

    Minified

    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)}
    

    Here is a demo I threw together. Notice the lack of loops :-)

    // Create a 5 row, by 9 column matrix.
    var m = CoordinateMatrix(5, 9);
    
    // Make the matrix an irregular shape.
    m[2] = m[2].slice(0, 5);
    m[4].pop();
    
    // Transpose and print the matrix.
    println(formatMatrix(transpose(m)));
    
    function Matrix(rows, cols, defaultVal) {
        return AbstractMatrix(rows, cols, function(r, i) {
            return arrayFill(cols, defaultVal);
        });
    }
    function ZeroMatrix(rows, cols) {
        return AbstractMatrix(rows, cols, function(r, i) {
            return zeroFill(cols);
        });
    }
    function CoordinateMatrix(rows, cols) {
        return AbstractMatrix(rows, cols, function(r, i) {
            return zeroFill(cols).map(function(c, j) {
                return [i, j];
            });
        });
    }
    function AbstractMatrix(rows, cols, rowFn) {
        return zeroFill(rows).map(function(r, i) {
            return rowFn(r, i);
        });
    }
    /** Matrix functions. */
    function formatMatrix(matrix) {
        return matrix.reduce(function (result, row) {
            return result + row.join('\t') + '\n';
        }, '');
    }
    function copy(matrix) {  
        return zeroFill(matrix.length).map(function(r, i) {
            return zeroFill(getMatrixWidth(matrix)).map(function(c, j) {
                return matrix[i][j];
            });
        });
    }
    function transpose(matrix) {  
        return zeroFill(getMatrixWidth(matrix)).map(function(r, i) {
            return zeroFill(matrix.length).map(function(c, j) {
                return matrix[j][i];
            });
        });
    }
    function getMatrixWidth(matrix) {
        return matrix.reduce(function (result, row) {
            return Math.max(result, row.length);
        }, 0);
    }
    /** Array fill functions. */
    function zeroFill(n) {
      return new Array(n+1).join('0').split('').map(Number);
    }
    function arrayFill(n, defaultValue) {
        return zeroFill(n).map(function(value) {
            return defaultValue || value;
        });
    }
    /** Print functions. */
    function print(str) {
        str = Array.isArray(str) ? str.join(' ') : str;
        return document.getElementById('out').innerHTML += str || '';
    }
    function println(str) {
        print.call(null, [].slice.call(arguments, 0).concat(['<br />']));
    }
    #out {
        white-space: pre;
    }
    <div id="out"></div>

    0 讨论(0)
  • 2020-11-22 02:23

    Many good answers here! I consolidated them into one answer and updated some of the code for a more modern syntax:

    One-liners inspired by Fawad Ghafoor and Ó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]));
    }
    

    Functional approach style with reduce by Andrew Tatomyr

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

    Lodash/Underscore by marcel

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

    Vanilla approach

    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;
    }
    

    Vanilla in-place ES6 approach inspired by Emanuel Saringan

    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]];
        }
      }
    }
    
    0 讨论(0)
提交回复
热议问题