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]));
mapvolá poskytnutoucallbackfunkci jednou pro každý prvek v poli, v pořadí, a vytváří nové pole z výsledků.callbackje 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.
callbackje 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;
}
}
}
