[javascript] Transposing a 2D-array in JavaScript

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 array:

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

It's not difficult to programmatically do so using loops:

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

This, however, seems bulky, and I feel like there should be an easier way to do it. Is there?

This question is related to javascript arrays matrix transpose

The answer is


Just another variation using Array.map. Using indexes allows to transpose matrices where 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]; 
    }); 
});

All there is to transposing is mapping the elements column-first, and then by row.


I think this is slightly more readable. It uses Array.from and logic is identical to using nested loops:

_x000D_
_x000D_
var arr = [_x000D_
  [1, 2, 3, 4],_x000D_
  [1, 2, 3, 4],_x000D_
  [1, 2, 3, 4]_x000D_
];_x000D_
_x000D_
/*_x000D_
 * arr[0].length = 4 = number of result rows_x000D_
 * arr.length = 3 = number of result cols_x000D_
 */_x000D_
_x000D_
var result = Array.from({ length: arr[0].length }, function(x, row) {_x000D_
  return Array.from({ length: arr.length }, function(x, col) {_x000D_
    return arr[col][row];_x000D_
  });_x000D_
});_x000D_
_x000D_
console.log(result);
_x000D_
_x000D_
_x000D_

If you are dealing with arrays of unequal length you need to replace arr[0].length with something else:

_x000D_
_x000D_
var arr = [_x000D_
  [1, 2],_x000D_
  [1, 2, 3],_x000D_
  [1, 2, 3, 4]_x000D_
];_x000D_
_x000D_
/*_x000D_
 * arr[0].length = 4 = number of result rows_x000D_
 * arr.length = 3 = number of result cols_x000D_
 */_x000D_
_x000D_
var result = Array.from({ length: arr.reduce(function(max, item) { return item.length > max ? item.length : max; }, 0) }, function(x, row) {_x000D_
  return Array.from({ length: arr.length }, function(x, col) {_x000D_
    return arr[col][row];_x000D_
  });_x000D_
});_x000D_
_x000D_
console.log(result);
_x000D_
_x000D_
_x000D_


You can do it in in-place by doing only one pass:

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

A library-free implementation in TypeScript that works for any matrix shape that won't truncate your arrays:

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

If you have an option of using Ramda JS and ES6 syntax, then here's another way to do it:

_x000D_
_x000D_
const transpose = a => R.map(c => R.map(r => r[c], a), R.keys(a[0]));_x000D_
_x000D_
console.log(transpose([_x000D_
  [1, 2, 3, 4],_x000D_
  [5, 6, 7, 8],_x000D_
  [9, 10, 11, 12]_x000D_
])); // =>  [[1,5,9],[2,6,10],[3,7,11],[4,8,12]]
_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.22.1/ramda.min.js"></script>
_x000D_
_x000D_
_x000D_


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

You can achieve this without loops by using the following.

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

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


I found the above answers either hard to read or too verbose, so I write one myself. And I think this is most intuitive way to implement transpose in linear algebra, you don't do value exchange, but just insert each element into the right place in the new matrix:

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
}

You could use underscore.js

_.zip.apply(_, [[1,2,3], [1,2,3], [1,2,3]])

shortest way with lodash/underscore and es6:

_.zip(...matrix)

where matrix could be:

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

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

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

One-liner that does not change given array.

a[0].map((col, i) => a.map(([...row]) => row[i]))

I didn't find an answer that satisfied me, so I wrote one myself, I think it is easy to understand and implement and suitable for all situations.

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

_x000D_
_x000D_
const transpose = array => array[0].map((r, i) => array.map(c => c[i]));_x000D_
console.log(transpose([[2, 3, 4], [5, 6, 7]]));
_x000D_
_x000D_
_x000D_


here is my implementation in modern browser (without dependency):

transpose = m => m[0].map((x,i) => m.map(x => x[i]))

Another approach by iterating the array from outside to inside and reduce the matrix by mapping inner values.

_x000D_
_x000D_
const_x000D_
    transpose = array => array.reduce((r, a) => a.map((v, i) => [...(r[i] || []), v]), []),_x000D_
    matrix = [[1, 2, 3], [1, 2, 3], [1, 2, 3]];_x000D_
_x000D_
console.log(transpose(matrix));
_x000D_
_x000D_
_x000D_


Edit: This answer would not transpose the matrix, but rotate it. I didn't read the question carefully in the first place :D

clockwise and counterclockwise rotation:

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

If using RamdaJS is an option, this can be achieved in one line: R.transpose(myArray)


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

Neat and pure:

[[0, 1], [2, 3], [4, 5]].reduce((prev, next) => next.map((item, i) =>
    (prev[i] || []).concat(next[i])
), []); // [[0, 2, 4], [1, 3, 5]]

Previous solutions may lead to failure in case an empty array is provided.

Here it is as a function:

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]]));

Update. It can be written even better with spread operator:

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

Since nobody so far mentioned a functional recursive approach here is my take. An adaptation of Haskell's Data.List.transpose.

_x000D_
_x000D_
var transpose = as => as.length ? as[0].length ? [as.reduce((rs, a) => a.length ? (rs.push(a[0]), rs) :
    rs, []
  ), ...transpose(as.map(a => a.slice(1)))] :
  transpose(as.slice(1)) :
  [],
  mtx = [
    [1],
    [1, 2],
    [1, 2, 3]
  ];

console.log(transpose(mtx))
_x000D_
.as-console-wrapper {
  max-height: 100% !important
}
_x000D_
_x000D_
_x000D_


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to arrays

PHP array value passes to next row Use NSInteger as array index How do I show a message in the foreach loop? Objects are not valid as a React child. If you meant to render a collection of children, use an array instead Iterating over arrays in Python 3 Best way to "push" into C# array Sort Array of object by object field in Angular 6 Checking for duplicate strings in JavaScript array what does numpy ndarray shape do? How to round a numpy array?

Examples related to matrix

How to get element-wise matrix multiplication (Hadamard product) in numpy? How can I plot a confusion matrix? Error: stray '\240' in program What does the error "arguments imply differing number of rows: x, y" mean? How to input matrix (2D list) in Python? Difference between numpy.array shape (R, 1) and (R,) Counting the number of non-NaN elements in a numpy ndarray in Python Inverse of a matrix using numpy How to create an empty matrix in R? numpy matrix vector multiplication

Examples related to transpose

Converting rows into columns and columns into rows using R Postgres - Transpose Rows to Columns Transposing a 2D-array in JavaScript What is the fastest way to transpose a matrix in C++? Excel VBA - Range.Copy transpose paste Transpose list of lists Transposing a 1D NumPy array An efficient way to transpose a file in Bash Transpose/Unzip Function (inverse of zip)?