我有一个数组的数组,就像这样:
[
[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;
}
然而,这看起来很笨重,我觉得应该有更简单的方法来做到这一点。是吗?
这个,不仅是一个超级高效的解,而且是一个很短的解。
算法时间复杂度:O(n log n)
const matrix = [
[1,1,1,1],
[2,2,2,2],
[3,3,3,3],
[4,4,4,4]
];
matrix.every((r, i, a) => (
r.every((_, j) => (
j = a.length-j-1,
[ r[j], a[j][i] ] = [ a[j][i], r[j] ],
i < j-1
)),
i < length-2
));
console.log(matrix);
/*
Prints:
[
[1,2,3,4],
[1,2,3,4],
[1,2,3,4],
[1,2,3,4]
]
*/
上面的例子将只进行6次迭代。
对于更大的矩阵,比如100x100,它将进行4900次迭代,这比这里提供的任何其他解决方案快51%。
原理很简单,你只遍历矩阵对角线的上半部分,因为对角线永远不会改变,下对角线的下半部分和上半部分互换了,所以没有理由也遍历它。这样可以节省大量的运行时间,特别是在大型矩阵中。
扩展语法不应该用作push的替代品,它只应该在你不想改变现有数组的时候使用。
算法:
对于每一列,只要检查该列是否在结果矩阵中有一行,如果已经有一行,那么简单地推元素,否则创建一个新的行数组,然后推。
因此,与上面的许多其他解决方案不同,这个解决方案不会一次又一次地创建新数组,而是将相同的数组推入。
另外,花点时间了解Nullish Coalescing Operator的用法。
常量
转置= arr => arr。foreach ((v, i) => (m[i]) ??= [], m[i].push(v))), m), []),
矩阵= [[1,2,3],[1,2,3],[1,2,3]]
console.log(转置矩阵)
这里有很多好答案!我把它们合并成一个答案,并更新了一些代码以获得更现代的语法:
灵感来自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设计的函数方法风格
function transpose(matrix) {
return matrix.reduce((prev, next) => next.map((item, i) =>
(prev[i] || []).concat(next[i])
), []);
}
洛达什/马塞尔的下划线
function tranpose(matrix) {
return _.zip(...matrix);
}
// Without spread operator.
function transpose(matrix) {
return _.zip.apply(_, [[1,2,3], [1,2,3], [1,2,3]])
}
Vigrant的更简单的Lodash/Underscore解决方案
_.unzip(matrix);
香草的方法
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;
}
由伊曼纽尔·萨林根启发的香草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]];
}
}
}