207

次のような配列の配列があります。

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

ただし、これはかさばるように思えます。もっと簡単な方法が必要だと思います。ある?

4

25 に答える 25

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

map指定された関数を配列内の各要素に対して順番に 1 回呼び出しcallback、結果から新しい配列を構築します。callback値が割り当てられている配列のインデックスに対してのみ呼び出されます。削除されたインデックス、または値が割り当てられていないインデックスに対しては呼び出されません。

callback要素の値、要素のインデックス、およびトラバースされる Array オブジェクトの 3 つの引数で呼び出されます。[ソース]

于 2013-07-02T14:48:17.927 に答える
56

これが最新のブラウザでの私の実装です(依存関係なし):

transpose = m => m[0].map((x,i) => m.map(x => x[i]))
于 2016-03-22T20:27:44.573 に答える
54

ここに多くの良い答えがあります!それらを 1 つの回答に統合し、コードの一部をより最新の構文に更新しました。

ファワド・ガフールとオスカー・ゴメス・アルカニスにインスパイアされたワンライナー

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/アンダースコア by marcel

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

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]];
    }
  }
}
于 2017-10-18T07:54:47.563 に答える
42

underscore.jsを使用できます

_.zip.apply(_, [[1,2,3], [1,2,3], [1,2,3]])
于 2013-07-02T14:51:26.480 に答える
32

lodash/underscorees6: _

_.zip(...matrix)

どこにあるmatrix可能性があります:

const matrix = [[1,2,3], [1,2,3], [1,2,3]];
于 2015-06-23T11:18:56.940 に答える
2

以下を使用して、ループなしでこれを実現できます。

非常にエレガントに見え、Underscore.jsのjQueryなどの依存関係は必要ありません。

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>

于 2015-02-20T17:29:14.067 に答える
2

const transpose = array => array[0].map((r, i) => array.map(c => c[i]));
console.log(transpose([[2, 3, 4], [5, 6, 7]]));

于 2019-12-04T07:34:56.973 に答える
1

これまで誰も機能的再帰的アプローチについて言及していないので、ここでは私の見解です。Haskell のData.List.transpose.

var transpose = as => as.length ? as[0].length ? [as.reduce((rs, a) => a.length ? (rs.push(a[0]), rs) :
    rs, []
  ), ...transpose(as.map(a => a.slice(1)))] :
  transpose(as.slice(1)) :
  [],
  mtx = [
    [1],
    [1, 2],
    [1, 2, 3]
  ];

console.log(transpose(mtx))
.as-console-wrapper {
  max-height: 100% !important
}

于 2020-03-31T15:43:04.903 に答える
0

これは、非常に効率的なものであるだけでなく、かなり短いソリューションです。

アルゴリズム時間の複雑さ: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 の場合、4,900 回の反復が行われます。これは、ここで提供されている他のどのソリューションよりも 51% 高速です。

原理は単純です。対角線は決して変化せず、対角線の下半分は上半分と一緒に切り替えられるため、マトリックスの対角線の上半分のみを反復処理するため、それを反復処理する理由もありません。このようにして、特に大規模なマトリックスで、実行時間を大幅に節約できます。

于 2021-04-07T15:53:03.243 に答える
0

ここに TS バージョンを追加します。

const transpose = <T>(m: Array<Array<T>>): Array<Array<T>> => m[0].map((_, i) => m.map(x => x[i]));
于 2021-12-03T08:30:29.607 に答える
-1
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;
}
于 2013-07-02T14:54:24.530 に答える