Vyhledávání na webu

Transponování 2D pole v JavaScriptu


Mám pole polí, něco jako:

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

Chtěl bych to transponovat, abych získal následující pole:

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

Není těžké to programově udělat pomocí smyček:

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

To se však zdá objemné a mám pocit, že by měla existovat snadnější cesta, jak to udělat. Existuje?

Odpověď č. 1

output = array[0].map((_, colIndex) => array.map(row => row[colIndex]));

map volá poskytnutou callback funkci jednou pro každý prvek v poli, v pořadí, a vytváří nové pole z výsledků. callback je volána pouze pro indexy pole, které mají přiřazené hodnoty; není volána pro indexy, které byly smazány nebo kterým nikdy nebyla přiřazena hodnota.

callback je volán se třemi argumenty: hodnota prvku, index prvku a objekt Array, který je právě procházen. [source]

Odpověď č. 2

Tady je hodně dobrých odpovědí! Spojil jsem je do jedné odpovědi a aktualizoval část kódu pro modernější syntaxi:

Jednoduché vtipy inspirované Fawadem Ghafoorem a Óscarem Gómezem Alcañizem

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

Funkční přístup se stylem reduce od Andrewa Tatomyra

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

Lodash/Underscore od marcel

function transpose(matrix) {
  return _.zip(...matrix);
}

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

Ještě jednodušší řešení Lodash/Underscore od Vigranta

_.unzip(matrix);

Vanilkový přístup

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 přístup ES6 na místě inspirovaný Emanuel Saringanem

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

Odpověď č. 3

tady je moje implementace v moderním prohlížeči (bez závislostí):

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

Odpověď č. 4

Mohl bys použít underscore.js

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

Odpověď č. 5

nejkratší cesta s lodash/underscore a es6:

_.zip(...matrix)

kde matrix může být:

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

Odpověď č. 6

Čistý a čistý:

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

Předchozí řešení může vést k selhání v případě, že je poskytnuto prázdné pole.

Tady je to jako funkce:

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

Aktualizace. Lze to napsat ještě lépe pomocí operátoru rozptýlení:

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

Odpověď č. 7

Můžete to provést na místě tím, že uděláte jen jeden průchod:

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

Související články