All articles

Matrix transposition in one line of code

A JavaScript function for transposing matrices.

A transposed matrix has properties that are very useful mathematically. As programmers, we sometimes work with two-dimensional arrays and need to extract information from a particular column. Matrix transposition is useful here too.

Until now, when my language did not support matrix manipulation natively or have a library for it, I used two loops to obtain the columns:

columns = new Array(matrix[0].length);

// Necesitamos inicializar cada elemento del arreglo columns como un array
// para poder utilizar push en el ciclo que extrae las columnas.
for (let j = 0; j < columns.length; j++) {
      columns[j] = [matrix[0][j]];
}

// Iteramos todas las filas de la matrix
for (let i = 0; i < matrix.length; i++) {
        // Iteramos todas las columnas    
        for (let j = 0; j < columns.length; j++) {
          columns[j].push(this.matrix[i][j]);
        }
    }

The previous solution works, but my mentor recommended looking for something more idiomatic in JavaScript. After trying several approaches, I searched online for help because I could not find an efficient solution. What I found really surprised me; understanding it has broadened how I approach this kind of problem. Here is the solution:

columns = matrix[0].map((_, colIndex) => matrix.map(row => row[colIndex]));  

Short, precise, elegant and cryptic the first time you see it. The idea is to nest two map functions.

The first map extracts the column indexes from matrix[0]. We are not interested in the element's value, so we use _.

matrix[0].map((_, colIndex))

The second extracts the elements of the column.

matrix.map(row => row[colIndex])

I found the solution here: Stack Overflow, Web Archive.

Implementing the same idea with two loops would look like this:

// Iteramos la primera fila de la matrix
for (let i = 0; i < matrix[0].length; i++) {
        // Iteramos todas las filas de la matrix    
        for (let j = 0; j < matrix.length; j++) {
          // Extraemos el valor del elemento en la columna i    
          columns[i].push(this.matrix[j][i]);
        }
    }

One thing I did not understand was why we could use a variable declared outside a function. The JavaScript manual explains it very well: let: Scoping rules.

References