257 votes

Transposition d'un tableau 2D en JavaScript

J'ai un tableau de tableaux, quelque chose comme.. :

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

Je voudrais le transposer pour obtenir le tableau suivant :

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

Il n'est pas difficile de le faire par programmation en utilisant des boucles :

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

Cependant, cela semble encombrant, et j'ai l'impression qu'il devrait y avoir un moyen plus facile de le faire. Y en a-t-il un ?

4voto

Rafael Rozon Points 124

Si vous utilisez RamdaJS est une option, cela peut être réalisé en une seule ligne : R.transpose(myArray)

3voto

Spread ne doit pas être utilisée comme une alternative à la syntaxe push il ne doit être utilisé que lorsque vous ne voulez pas modifier le tableau existant.

Algorithme : Pour chaque colonne, vérifiez simplement si pour cette colonne il y a une ligne dans la matrice résultante, s'il y a déjà une ligne, alors simplement push l'élément, sinon créer un nouveau tableau de rangées et ensuite push .

Ainsi, contrairement à de nombreuses autres solutions ci-dessus, cette solution ne crée pas de nouveaux tableaux encore et encore, mais pousse sur le même tableau.

Prenez également le temps d'apprécier l'utilisation de la Opérateur de coalescence nul .

const 
  transpose = arr => arr.reduce((m, r) => (r.forEach((v, i) => (m[i] ??= [], m[i].push(v))), m), []),
  matrix = [[1, 2, 3], [1, 2, 3], [1, 2, 3]]

console.log(transpose(matrix))

2voto

Mr. Polywhirl Points 3677

Vous pouvez y parvenir sans boucles en utilisant ce qui suit.

Il est très élégant et ne nécessite pas de dépendances telles que jQuery de 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);
}

Minimisé

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

Voici une démo que j'ai réalisée. Remarquez l'absence de boucles :-)

// 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>

2voto

ysle Points 37

ES6 1liners comme :

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

donc la même chose que celle d'Óscar, mais comme vous préférez la faire tourner dans le sens des aiguilles d'une montre :

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

let a = [
    [1,1,1]
    , ["_","_","1"]
]
let b = rotate(a);
let c = rotate(b);
let d = rotate(c);
console.log(`a ${a.join("\na ")}`);
console.log(`b ${b.join("\nb ")}`);
console.log(`c ${c.join("\nc ")}`);
console.log(`d ${d.join("\nd ")}`);

Rendement

a 1,1,1 
a _,_,1

b _,1
b _,1
b 1,1 

c 1,_,_
c 1,1,1

d 1,1
d 1,_
d 1,_

2voto

Aryan Firouzian Points 1008

Edit : Cette réponse ne transpose pas la matrice, mais la fait tourner. Je n'ai pas lu la question attentivement en premier lieu :D

rotation dans le sens des aiguilles d'une montre et dans le sens inverse :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X