El Blog de Webcu

Transposición de Matrices en una línea de código

October 29, 2019

La matriz transpuesta tiene un conjunto de propiedades que resultan muy útiles desde el punto de vista matemático. Como programadores a veces tenemos que trabajar con arreglos de dos dimensiones y necesitamos extraer información de una columna en específico, en este caso la transposición de matrices también nos resulta muy útil.

Hasta ahora, si el lenguaje con que trabajo no soporta de manera nativa la manipulación de matrices o no tiene una librería para ello, empleó dos ciclos para obtener las columnas:

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

La solución anterior funciona, pero mi mentor me recomendó buscar una solución más idiomática al estilo de JavaScript. Después de intentar abordar el problema desde diferentes ángulos, decidí buscar ayuda en Internet porque no lograba encontrar una solución eficiente. La solución que encontré realmente me sorprendió y después de comprenderla me ha ayudado a ampliar la manera de enfocar problemas de este tipo. Esta es la solución:

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

Corta, precisa, elegante y cryptica la primera vez que la vemos. La idea es utilizar dos funciones map de manera recursiva.

La primera función map extrae el índice de las columnas de matrix[0], el valor del elemento no nos interesa por eso utilizamos _.

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

La segunda función extrae los elementos de la columna.

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

Encontré la solución aquí: Stackoverflow, Web Archive.

Utilizando dos ciclos para implementar la misma idea, sería:

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

Algo que no me quedaba claro, era porque podíamos utilizar una variable que fue declarada fuera de una función. El manual de JavaScript lo explica muy bien: let: Reglas de alcance.

Referencias


Jorge Glez

Escrito por Jorge Glez. Un ser humano con defectos y virtudes que intenta ser mejor cada día. Twitter