JavaScript 2D数组分组:是否有更优雅/优化的方式?

时间:2017-02-15 00:00:28

标签: multidimensional-array grouping

我有以下代码可以正常工作。 我只是想知道是否有更优雅/更优化的方式。

长“代码”简短,给出数据:

var myArray = [
  ['X', 'A', 0, 1, 'Y', 3],
  ['X', 'A', 4, 5, 'Y', 6],
  ['X', 'B', 6, 5, 'Y', 4],
  ['X', 'B', 3, 2, 'Y', 1],
  ['X', 'C', 7, 8, 'Y', 9],
];

假设我想按列索引1进行分组,只对列索引2, 3, 5求和。

预期结果是:

[
  ["A", 4, 6, 9],
  ["B", 9, 7, 5],
  ["C", 7, 8, 9]
]

// data
var myArray = [
  ['X', 'A', 0, 1, 'Y', 3],
  ['X', 'A', 4, 5, 'Y', 6],
  ['X', 'B', 6, 5, 'Y', 4],
  ['X', 'B', 3, 2, 'Y', 1],
  ['X', 'C', 7, 8, 'Y', 9],
];

// col that I want to group by
var colIndex = 1;

// cols I want to sum
var colsToSum = [2, 3, 5];

var arrayGroupBy = function(myArray, colIndex, colsToSum) {

  // get unique column values
  var uniqueValues = [];
  myArray.forEach(function(row) {
    if (uniqueValues.indexOf(row[colIndex]) === -1) {
      uniqueValues.push(row[colIndex]);
    }
  });

  var newData = [];
  uniqueValues.forEach(function(value) {

    // get filtered rows
    var filteredRows = myArray.filter(function(row) {
      return row[colIndex] === value;
    });

    var row = [value];

    // columns to sum
    colsToSum.forEach(function(num) {
      if (filteredRows.length === 1) {

        // push single row
        row.push(filteredRows[0][num]);

      } else {

        // sum row cols
        var total = filteredRows.reduce(function(sum, current) {
          return sum + current[num];
        }, 0);

        row.push(total);
      }

    });

    newData.push(row);
  });

  return newData;
};

console.log(arrayGroupBy(myArray, colIndex, colsToSum));

不幸的是我不能在这个上使用ES6 ......

谢谢!

1 个答案:

答案 0 :(得分:0)

我试图为您的问题找到解决方案。将有许多优秀的ES6功能可以使解决方案更具可读性/更清晰。但这是一个没有任何ES6功能的解决方案:

var groupBy = function(myArray, colIndex, colsToSum) {
  var obj = {};
  myArray.forEach(function(e) {
    if(!obj.hasOwnProperty(e)) {
      obj[e[colIndex]] = new Array(colsToSum.length + 1)
        .join('0').split('').map(parseFloat);
      }
  });

  myArray.forEach(function(row) {
    for (var i = 0; i < colsToSum.length; i++) {
      obj[row[colIndex]][i] += row[colsToSum[i]];
    }
  });

  return Object.keys(obj).map(function(key) {
    return [key].concat(obj[key]);
  });
}

说明:

  • 具有属性&#39; A&#39;,&#39; B&#39;和&#39; C&#39;将被创建。
  • 数组[0, 0, 0]将分配给每个媒体资源。
  • 循环myArraycolsToSum并将值添加到正确的对象属性
  • 将对象转换为数组并将其返回

也许有更好的解决方案:)