Преобразовать массив строк в массив столбцов - PullRequest
1 голос
/ 12 мая 2011

Какой самый элегантный способ превратить любой массив строк (равной длины) в массив столбцов?

Например:

[1,2,3]
[4,5,6]

# To    

[1,4]
[2,5]
[3,6]

Thisэто то, что у меня есть до сих пор:

grid = [
  [1,2,3]
  [4,5,6]
]

grid2 = []

for i in grid[0]
  grid2.push []

for row, y in grid
  for el, x in row
    grid2[x].push el

Может быть, есть даже 1-лайнер, который бы это сделал?

Ответы [ 4 ]

6 голосов
/ 12 мая 2011

В Javascript, если вы работаете в среде с методами массива ECMAScript 5, функция map() прекрасно работает для этого:

var grid2 = grid[0].map(function(col, i) {
    return grid.map(function(row) {
        return row[i];
    });
});

Это может быть однострочно, если вы убили строкубрейки.:)

CoffeeScript:

grid[0].map (col, i) -> grid.map (row) -> row[i]
3 голосов
/ 12 мая 2011

Не используйте for ..in с массивами, где важен порядок !!

Использование for..in с массивами имеет следующие опасности:

  1. Будут возвращены все перечисляемые свойства массива , в том числе свойства Array.prototype и самого массива, поэтому либо вы должны быть абсолютно уверены, что таких расширений не было, либо вы должны сделать hasOwnProperty и проверки числовых индексов

  2. Порядок, в котором возвращаются ключи, не гарантируется и может быть легко нарушен - IE возвращает их в порядке их добавления, поэтому, если они добавляются не по порядку (например, с использованием уменьшающего цикла while, который является довольно часто) они будут возвращены в обратном порядке

Попробуйте следующее в Firefox и IE:

var a = [0,1,2,3];
var b = [];
var i = a.length;
while (i--) {
  b[i] = a[i];
}
var s = [];
for (var p in b) {
  s.push(b[p]);
}

alert(b + '\n' + s);

// Firefox: 0,1,2,3
//          0,1,2,3

// IE: 0,1,2,3
//     3,2,1,0

Там, где важен порядок, только используют циклы, где вы явно обращаетесь к ключам в нужном вам порядке. Это также относится к объектам, поскольку в javascript порядок, в котором свойства возвращаются с использованием for..in для всех объектов, зависит от реализации и различается в разных браузерах (отмечая, что в javascript все является объектом).

For..in нормально использовать с массивами, где вышеуказанные проблемы либо не важны, либо решаются. Это удобный инструмент для разреженных массивов и доступа к нечисловым перечислимым свойствам.

Общая функция транспонирования:

function rows2cols(a) {
  var r = [];
  var t;

  for (var i=0, iLen=a.length; i<iLen; i++) {
    t = a[i];

    for (var j=0, jLen=t.length; j<jLen; j++) {
      if (!r[j]) {
        r[j] = [];
      }
      r[j][i] = t[j];
    }
  }
  return r;
}

Он может быть сокращен и оптимизирован, но вышеприведенная функция является достаточно эффективной и легко поддерживаемой.

2 голосов
/ 12 мая 2011

CoffeeScript:

((row[i] for row in grid) for i in [0...grid[0].length])
1 голос
/ 12 мая 2011

Попробуйте:

var new_grid = [];
for(var i = 0; i < grid[0].length; i++){
    new_grid.push([grid[0][i], grid[1][i]]); 
    // this is all under assumption that all the arrays are the same size
}

Получите ли вы результат:

new_grid = [
   [1,4],
   [2,5],
   [3,6],
]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...