JavaScript에서 2D 배열 전치
다음과 같은 배열 배열이 있습니다.
[
[1,2,3],
[1,2,3],
[1,2,3],
]
다음 배열을 얻기 위해 전치하고 싶습니다.
[
[1,1,1],
[2,2,2],
[3,3,3],
]
루프를 사용하여 프로그래밍 방식으로 그렇게하는 것은 어렵지 않습니다.
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;
}
그러나 이것은 부피가 커 보이며 더 쉬운 방법이 있어야한다고 생각합니다. 있습니까?
array[0].map((col, i) => array.map(row => row[i]));
map
callback
배열의 각 요소에 대해 제공된 함수를 순서대로 한 번 호출 하고 결과에서 새 배열을 구성합니다.callback
값이 할당 된 배열의 인덱스에 대해서만 호출됩니다. 삭제되었거나 값이 할당되지 않은 인덱스에 대해서는 호출되지 않습니다.
callback
요소의 값, 요소의 색인 및 순회되는 Array 객체의 세 가지 인수로 호출됩니다. [출처]
underscore.js를 사용할 수 있습니다
_.zip.apply(_, [[1,2,3], [1,2,3], [1,2,3]])
다음은 최신 브라우저에서 구현하지 않은 종속성입니다.
transpose = m => m[0].map((x,i) => m.map(x => x[i]))
lodash
/ underscore
와 가장 짧은 방법 es6
:
_.zip(...matrix)
어디 matrix
있을 수 있습니다 :
const matrix = [[1,2,3], [1,2,3], [1,2,3]];
여기에 많은 좋은 답변이 있습니다! 나는 그것들을 하나의 답변으로 통합하고보다 현대적인 구문을 위해 코드를 업데이트했습니다.
Fawad Ghafoor 와 Óscar Gómez Alcañiz에서 영감을 얻은 원 라이너
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]));
}
Andrew Tatomyr의 Reduce를 사용한 기능적 접근 방식
function transpose(matrix) {
return matrix.reduce((prev, next) => next.map((item, i) =>
(prev[i] || []).concat(next[i])
), []);
}
에 의해 Lodash / 밑줄 마르셀
function tranpose(matrix) {
return _.zip(...matrix);
}
// Without spread operator.
function transpose(matrix) {
return _.zip.apply(_, [[1,2,3], [1,2,3], [1,2,3]])
}
바닐라 접근
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;
}
Emanuel Saringan에서 영감을 얻은 바닐라 인플레 이스 ES6 접근 방식
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]];
}
}
}
한 번만 통과하면 제자리에서 할 수 있습니다.
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;
}
}
}
단정하고 순수한 :
[[0, 1], [2, 3], [4, 5]].reduce((prev, next) => next.map((item, i) =>
(prev[i] || []).concat(next[i])
), []); // [[0, 2, 4], [1, 3, 5]]
빈 어레이가 제공되는 경우 이전 솔루션으로 인해 오류가 발생할 수 있습니다.
다음은 함수입니다.
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]]));
최신 정보. 스프레드 연산자를 사용하여 더 잘 작성할 수 있습니다.
const transpose = matrix => matrix.reduce(($, row) =>
row.map((_, i) => [...($[i] || []), row[i]]),
[]
)
를 사용하는 또 다른 변형 Array.map
입니다. 인덱스를 사용하면 다음과 같은 행렬을 전치 할 수 있습니다 M != N
.
// Get just the first row to iterate columns first
var t = matrix[0].map(function (col, c) {
// For each column, iterate all rows
return matrix.map(function (row, r) {
return matrix[r][c];
});
});
전치해야 할 것은 요소를 열 단위로 매핑 한 다음 행 단위로 매핑하는 것입니다.
Ramda JS 및 ES6 구문을 사용하는 옵션이있는 경우 다른 방법으로 수행 할 수 있습니다.
const transpose = a => R.map(c => R.map(r => r[c], a), R.keys(a[0]));
console.log(transpose([
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
])); // => [[1,5,9],[2,6,10],[3,7,11],[4,8,12]]
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.22.1/ramda.min.js"></script>
RamdaJS 사용 이 옵션 인 경우 한 줄로 수행 할 수 있습니다.R.transpose(myArray)
배열을 외부에서 내부로 반복하고 내부 값을 매핑하여 행렬을 줄이는 또 다른 방법입니다.
const
transpose = array => array.reduce((r, a) => a.map((v, i) => [...(r[i] || []), v]), []),
matrix = [[1, 2, 3], [1, 2, 3], [1, 2, 3]];
console.log(transpose(matrix));
편집 :이 답변은 행렬을 바꾸지 않고 회전시킵니다. 나는 처음부터 질문을주의 깊게 읽지 않았습니다.
시계 방향 및 반 시계 방향 회전 :
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;
}
다음을 사용하여 루프 없이이 작업을 수행 할 수 있습니다.
매우 우아해 보이며 jQuery of 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);
}
축소
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)}
여기 제가 함께 던진 데모가 있습니다. 루프 부족에 주목하십시오 :-)
// 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>
ES6 1 라이너 :
let invert = a => a[0].map((col, c) => a.map((row, r) => a[r][c]))
Óscar와 동일하지만 시계 방향으로 돌리십시오.
let rotate = a => a[0].map((col, c) => a.map((row, r) => a[r][c]).reverse())
위의 답변을 읽기가 어렵거나 너무 장황하다는 것을 알았으므로 직접 작성하십시오. 그리고 이것은 선형 대수로 전치를 구현하는 가장 직관적 인 방법이라고 생각합니다. 값 교환 을하지 않고 각 요소를 새 행렬의 올바른 위치에 삽입하십시오.
function transpose(matrix) {
const rows = matrix.length
const cols = matrix[0].length
let grid = []
for (let col = 0; col < cols; col++) {
grid[col] = []
}
for (let row = 0; row < rows; row++) {
for (let col = 0; col < cols; col++) {
grid[col][row] = matrix[row][col]
}
}
return grid
}
나는 이것이 약간 더 읽기 쉽다고 생각합니다. 그것은 사용 Array.from
및 로직은 중첩 루프를 사용하여 동일합니다 :
var arr = [
[1, 2, 3, 4],
[1, 2, 3, 4],
[1, 2, 3, 4]
];
/*
* arr[0].length = 4 = number of result rows
* arr.length = 3 = number of result cols
*/
var result = Array.from({ length: arr[0].length }, function(x, row) {
return Array.from({ length: arr.length }, function(x, col) {
return arr[col][row];
});
});
console.log(result);
길이가 다른 배열을 다루는 경우 arr[0].length
다른 것으로 바꿔야 합니다.
var arr = [
[1, 2],
[1, 2, 3],
[1, 2, 3, 4]
];
/*
* arr[0].length = 4 = number of result rows
* arr.length = 3 = number of result cols
*/
var result = Array.from({ length: arr.reduce(function(max, item) { return item.length > max ? item.length : max; }, 0) }, function(x, row) {
return Array.from({ length: arr.length }, function(x, col) {
return arr[col][row];
});
});
console.log(result);
function invertArray(array,arrayWidth,arrayHeight) {
var newArray = [];
for (x=0;x<arrayWidth;x++) {
newArray[x] = [];
for (y=0;y<arrayHeight;y++) {
newArray[x][y] = array[y][x];
}
}
return newArray;
}
A library-free implementation in TypeScript that works for any matrix shape that won't truncate your arrays:
const rotate2dArray = <T>(array2d: T[][]) => {
const rotated2d: T[][] = []
return array2d.reduce((acc, array1d, index2d) => {
array1d.forEach((value, index1d) => {
if (!acc[index1d]) acc[index1d] = []
acc[index1d][index2d] = value
})
return acc
}, rotated2d)
}
One-liner that does not change given array.
a[0].map((col, i) => a.map(([...row]) => row[i]))
reverseValues(values) {
let maxLength = values.reduce((acc, val) => Math.max(val.length, acc), 0);
return [...Array(maxLength)].map((val, index) => values.map((v) => v[index]));
}
참고URL : https://stackoverflow.com/questions/17428587/transposing-a-2d-array-in-javascript
'development' 카테고리의 다른 글
기존 git 프로젝트를 GitLab으로 가져 오시겠습니까? (0) | 2020.07.01 |
---|---|
ASP.NET MVC를 사용하여 여러 매개 변수를 사용하여 라우팅 (0) | 2020.07.01 |
NHibernate.MappingException : XYZ에 대한 지속 자 없음 (0) | 2020.07.01 |
패션처럼 트리에서 자식 분기의 출력 (0) | 2020.07.01 |
Android의 기본 텍스트 크기는 얼마입니까? (0) | 2020.07.01 |