【问题标题】:Average of bidimensional array's columns with array.map()使用 array.map() 平均二维数组的列
【发布时间】:2017-05-30 17:44:41
【问题描述】:

我有一个如下所示的数组:

var array = [ [1,3,9],
              [4,6,8],
              [3,7,5],
              [2,8,4] ];

我想获得每列的平均数,但现在我只是想对它们求和。这是我的代码:

var sum = function(arr) {
  return arr.reduce(function(a, b) { return a + b; }, 0);
};

var tests = array.map(function(v, i) {
  return sum(array.map(function(v) { return v[i]; }))
});

return tests;

输出正确地转换了总和,但它似乎做了与行(4 行)一样多的总和,而不是 3 对应于列。这是输出:

tests = [10, 24, 26, NULL]

知道为什么会这样吗?如何仅针对行数而不是行数执行计算?

编辑:

我正在使用Nenad 的答案,它给出了正确的结果。但我需要在谷歌表格的脚本编辑器上实现它,它似乎不理解带有“=>”的缩短函数。我用更长的版本替换了缩短的部分,但我没有得到相同的结果。

var array = [ [1,3,9],
              [4,6,8],
              [3,7,5],
              [2,8,4] ];

var sums = array.reduce(function(r, e, i) {
    e.forEach(function(a,j) { r[j] = (r[j] || 0) + a;
                             if (i == array.length-1) { r = r.map(function(el){ return el/array.length; }); }
                            });
    return r;
  }, [])
  
console.log(sums);  

我看不出这个和缩短的版本有什么区别,但是这个又回来了:

sums = [0.15625, 0.75, 1.34375];

代替:

sums = [2.5, 6, 6.5];

总和是正确的,但是当我除以“el/array.length”甚至“el/4”时,结果是这3个奇怪的数字。我不明白那些来自哪里。我哪里做错了?

【问题讨论】:

    标签: javascript arrays multidimensional-array google-sheets


    【解决方案1】:

    您可以使用reduce()forEach() 来返回结果。

    var array = [
      [1, 3, 9],
      [4, 6, 8],
      [3, 7, 5],
      [2, 8, 4]
    ];
    
    var sums = array.reduce(function(r, e, i) {
      e.forEach((a, j) => r[j] = (r[j] || 0) + a)
      return r;
    }, [])
    
    console.log(sums)

    要计算每列的平均值,您可以在数组的最后一次迭代中添加 map()

    var array = [
      [1, 3, 9],
      [4, 6, 8],
      [3, 7, 5],
      [2, 8, 4]
    ];
    
    var sums = array.reduce(function(r, e, i) {
      e.forEach((a, j) => r[j] = (r[j] || 0) + a)
      if (i == array.length - 1) r = r.map(el => el / array.length);
      return r;
    }, [])
    
    console.log(sums)

    【讨论】:

    • 非常感谢内纳德!这个其他版本确实适用于 Google 的脚本编辑器。我用一些括号搞砸了很多 -_- 整个 .map/.reduce 函数对我来说是非常新的。再次感谢内纳德!
    【解决方案2】:

    要获得每列的平均值,您首先必须知道列的数量。然后用map() 抓取每一列,并用reduce() 总结所有内容

    现在我们有了列、总和,然后除以列长度。

    const arrayColumn = (a, n) => a.map(x => x[n]);
    const arraySum    = (a) => a.reduce((b,c) => b + c);
    
    var arr = [ 
     [1,3,9],
     [4,6,8],
     [3,7,5],
     [2,8,4] 
    ];
    
    for(i=0; i<arr[0].length; i++){
      console.log(arraySum((col = arrayColumn(arr, i))) / col.length);
    }

    【讨论】:

      【解决方案3】:

      这会将二维行数组转换为二维列数组,然后将每个内部列数组映射到平均值。有一些样板可以使内部 reduce 不可变,您可以使用 lodash/fp 或其他库来清理它。

      const array = [ 
        [1,3,9],
        [4,6,8],
        [3,7,5],
        [2,8,4] 
      ];
      
      const averageColumns = array => array.reduce((acc, row) => {
        return row.reduce((accRow, col, index) => {
          const cols = accRow[index] || [];
          return [...accRow.slice(0, index), cols.concat(col), ...accRow.slice(index + 1)];
      
        }, acc);
      }, []).map(avg);
      
      const avg = array => array.reduce((acc, next) => acc + next, 0) / array.length;
      
      console.log(averageColumns(array));

      【讨论】:

        【解决方案4】:

        map() + reduce() 解决方案

        var array = [ [1,3,9], [4,6,8], [3,7,5], [2,8,4] ];
        
        
        array.map(function(item, i, arr) {
        	arr[i] = item.reduce((a, b) => a + b, 0) / 2;
          	console.log(arr[i])
        });

        我正在修改你的代码
        你这里有错误return sum(array.map(function(v) { return v[i]; }))

        var array = [ [1,3,9],
                      [4,6,8],
                      [3,7,5],
                      [2,8,4] ];
        function sum(arr) {
          return arr.reduce(function(a, b) { return a + b; }, 0);
        };
        
        var tests = array.map(function(v, i, arr) {
          return sum(arr[i])
        });
        
        tests;
        

        【讨论】:

          【解决方案5】:

          您可以转置数组数组,
          流行的实用程序库(例如 ramda)具有转置实现,
          但很容易实现自己的:

          const trans = arr => arr[0].map((_,i) => arr.map(x => x[i]))
          
          var array = [ 
           [1,3,9],
           [4,6,8],
           [3,7,5],
           [2,8,4] 
          ];
          const res = trans(array)
          console.log(res)
          
          
          // to get the sum you can use reduce
          console.log(res.map( x => x.reduce((a,b) => a + b )))

          【讨论】:

            【解决方案6】:

            我会这样做;

            var array = [ [1,3,9],
                          [4,6,8],
                          [3,7,5],
                          [2,8,4] ];
               result = array.map(a => a.reduce((p,c,_,a) => p + c/a.length,0));
            console.log(result);

            根据 cmets... 是的,他们是对的,正确的解决方案应该是通过 .map().reduce() 的切换;

            var array = [ [1,3,9],
                          [4,6,8],
                          [3,7,5],
                          [2,8,4] ],
               result = array.reduce((p,c) => p.map((n,i) => n + c[i]/array.length), Array(array[0].length).fill(0));
            console.log(result);

            【讨论】:

            • 请求的是列的总和,而不是索引的总和。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-02-19
            • 1970-01-01
            • 1970-01-01
            • 2013-07-08
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多