在Javascript中需要帮助理解这个片段(转置数组)

时间:2016-03-31 18:54:41

标签: javascript arrays algorithm matrix transpose

我发现这段代码可以在另一篇文章中转换数组,但我不明白为什么我们只对数组a[0]的第一个元素进行操作。此外,下划线的表现如何? (当我谷歌下划线时,我得到的只是下划线库)。

function transpose(a)
{
  return a[0].map(function (_, c) { return a.map(function (r) { return r[c]; }); });
}

3 个答案:

答案 0 :(得分:0)

代码确实转置了一个矩阵(2d数组)。

外部map调用在a[0]上运行,以便获取列索引并生成一个输出数组,其中列为" - " -long(如果输入为a mn ,它返回一个带 n 条目的新数组。未使用第一个参数,因此使用占位符标识符(_)。第二个参数(列索引)用于内部映射以访问正确的单元格。

在该调用中,进行另一次map调用,这次是在整个数组上进行的,这有效地映射了行。每行(一个单元格数组)转为单值r[c],这些行一起生成返回到外部地图的输出数组。

答案 1 :(得分:0)

让我们扩展代码以提高可读性并完成它:

// Pass an array to transpose: i.e. transpose(myArray);
function transpose(a){

  // return the array returned from calling the .map method
  // on the first item in the array (this assumes that the first
  // item in the array is, itself, an array:
  return a[0].map(
                   // Provide the function for the map to use
                   // This function can take 3 arguments for:
                   // currentValue, index, array
                   // The code below would access currentValue with _
                   // and index with c 
                   function (_, c) { 
                      // The mapping callback function's job is to return
                      // values that will be placed into a new array that
                      // the overall .map method creates. Here, the callback
                      // is calling .map on the original array:
                      return a.map( 
                          // This callback is using the variable r to 
                          // receive the currentValue of the array element
                          // being looped over (which is assumed to be an
                          // array itself here: 
                          function(r) {
                              // This function returns elemeent at index
                              // position: c from the array element r and
                              // adds this to the new array being created
                              // by the nested .map call
                              return r[c]; 
                          });
                   });
}

现在,作者只选择了参数名称:_,c和r,但使用.map()时,最好使用valindexarr(或名称非常相似),请记住.map()回调函数的参数代表什么。

此函数适用于传入的数组(a)的第一个元素,即a[0],它本身就是一个数组。

然后移动原始数组的元素,抓取与第一个数组对应的索引位置的元素,但是从第二个数组中获取元素。

答案 2 :(得分:0)

  

下划线的表现是什么?

map()的第一个参数名为_的原因是因为它未被使用。 下划线是usually picked by convention作为未使用参数的名称。

  

但我不明白为什么我们只对数组a [0]

的第一个元素起作用

使用a[0]是任意的。由于矩阵中的所有行都具有相同的长度,因此任何索引都可以工作。我们这样做是为了获得列数。

基本上,第一个map()遍历第一行(所有列),并且在每次迭代时,忽略当前列值并获取当前列索引。换句话说,第一个map()遍历矩阵的“宽度”,从左到右,每次抓取当前列索引。

第二个map()位于第一个map()内。这意味着它,对于每个列索引,迭代所有行(矩阵的高度),并且在每次迭代时,使用相应的列索引从当前行创建一个新行。

  • 需要注意的重要一点是map每次创建一个新数组,因此您创建一个新的转置矩阵,而不是以任何方式更改初始矩阵。

Visual Example

如果你从矩阵开始:

[ ['a1', 'a2', 'a3'] ]
[ ['b1', 'b2', 'b3'] ]

然后在每一步中,这是正在发生的事情(对原始矩阵使用M,对转置矩阵使用T):

// Step1
columnIndex = 0 
T[columnIndex][0] becomes M[0][columnIndex] which is "a1"
T[columnIndex][1] becomes M[1][columnIndex] which is "b1"
transposed row 0 becomes ["a1", "b1"]

// Step2
columnIndex = 1 
T[columnIndex][0] becomes M[0][columnIndex] which is "a2"
T[columnIndex][1] becomes M[1][columnIndex] which is "b2"
transposed row 1 becomes ["a2", "b2"]

// Step3
columnIndex = 2 
T[columnIndex][0] becomes M[0][columnIndex] which is "a3"
T[columnIndex][1] becomes M[1][columnIndex] which is "b3"
transposed row 2 becomes ["a3", "b3"]

你最终得到了一个转置矩阵:

[ ['a1', 'b1'] ]
[ ['a2', 'b2'] ]
[ ['a3', 'b3'] ]

这是具有更改格式和变量名称的代码,以更清楚地显示正在发生的事情。打开控制台,查看每个步骤中发生的情况。

var matrix = [];
matrix.push(['a1', 'a2', 'a3']); // first row
matrix.push(['b1', 'b2', 'b3']);

/*
  matrix = 
  [ ['a1', 'a2', 'a3'] ]
  [ ['b1', 'b2', 'b3'] ]
*/

function transpose(matrix) {
  var firstRow = matrix[0];

  var transposedMatrix = firstRow.map(function(UNUSED, columnIndex) {

    console.debug('\ncolumnIndex = %d', columnIndex);

    var transposedRow = matrix.map(function(row, idx) { // <-- idx is only used for logging, it's not necessary

      console.debug('T[%d][%d] = becomes %o', columnIndex, idx, row[columnIndex]);
      return row[columnIndex];

    });

    console.debug('transposed row %d becomes %o: ', columnIndex, transposedRow);

    return transposedRow;
  });

  return transposedMatrix;
}


var transposed = transpose(matrix);

/*
  transposed = 
  [ ['a1', 'b1'] ]
  [ ['a2', 'b2'] ]
  [ ['a3', 'b3'] ]
*/

console.dir(transposed);