使用Javascript,Underscore或Lodash进行分组+总和

时间:2016-03-09 16:57:36

标签: javascript underscore.js lodash

我想知道如何执行以下分组并总结Underscore或Lodash。

  

MY ARRAY:

[
{_id : "1", S : "2"},
{_id : "1", M : "4"},
{_id : "2", M : "1"},
{_id : "" , M : "1"},
{_id : "3", S : "3"}
]
  

渴望输出

[
{_id : "1", M : "4", S : "2", Total: "6"},
{_id : "2", M : "1", S : "0", Total: "1"},
{_id : "3", M : "0", S : "3", Total: "3"},
{_id : "",  M : "1", S : "0", Total: "1"}
]
  

我到目前为止

我坚信我到目前为止做了以下事情,但我无法弄清楚我的内容是什么?

var groups = _.groupBy(MyArray, function(value){
            return value._id;
        });

        var data = _.map(groups, function(group){
            return {
                _id: group[0]._id,
                M:  ?? ,
                S:  ?? ,
                T:  ?? 

            }
        });

5 个答案:

答案 0 :(得分:1)

使用普通javascript解决方案,使用Array.prototype.forEachArray.prototype.map函数

var obj = {}

// arr is your first array
arr.forEach(function(a) {
    var t = obj[a._id];
    if (t) {
        t.M += a.M ? parseInt(a.M, 10) : 0;
        t.S += a.S ? parseInt(a.S, 10) : 0;
        t.Total = parseInt(t.M, 10) + parseInt(t.S, 10);
    } else {
        t = {};
        t._id = a._id;
        t.M = a.M ? parseInt(a.M, 10) : 0;
        t.S = a.S ? parseInt(a.S, 10) : 0;
        t.Total = parseInt(t.M, 10) + parseInt(t.S, 10);
        obj[a._id] = t;
    }
});

var res = Object.keys(obj).map(function (k) {
    return obj[k];
})

console.log(res);

结果:

[ { _id: '1', M: 4, S: 2, Total: 6 },
  { _id: '2', M: 1, S: 0, Total: 1 },
  { _id: '3', M: 0, S: 3, Total: 3 },
  { _id: '', M: 1, S: 0, Total: 1 } ]

答案 1 :(得分:0)

这是一个普通Javascript中的提案,带有一个临时对象和一些数组方法。

var data = [{ _id: "1", S: "2" }, { _id: "1", M: "4" }, { _id: "2", M: "1" }, { _id: "", M: "1" }, { _id: "3", S: "3" }],
    result = function (data) {                // immediately invoked function expression
        var r = [], o = {};                   // declare the result and temp object
        data.forEach(function (a) {           // iterate over data
            if (!o[a._id]) {                  // check if id in object
                o[a._id] = {                  // if not build new object
                    _id: a._id,               // with the wanted properties
                    M: 0,                     // _id, a value taken for the key, too
                    S: 0,                     // M and S initialized with 0
                    Total: 0                  // Total as well initialised with 0
                };                            // push the reference of object to result
                r.push(o[a._id]);             // while we reference an object, the values
            }                                 // are the same in object o and in array r
            ['M', 'S'].forEach(function (k) { // iterate over M and S, the keys to sum
                o[a._id][k] += +a[k] || 0;    // add truthy value or 0 to group
                o[a._id].Total += +a[k] || 0; // take value or the default value 0 with
            });                               // a logical or
        });                                   // end of iteration
        return r;                             // return result
    }(data);

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');

答案 2 :(得分:0)

使用链式lodashv3.10.1groupBy() thru()keys()和{{1}的reduce() find()兼容版本}}:

merge()

答案 3 :(得分:0)

array = [
    {_id : "1", S : "2"},
    {_id : "1", M : "4"},
    {_id : "2", M : "1"},
    {_id : "" , M : "1"},
    {_id : "3", S : "3"}
    ];

array.reduce(function(previousValue, currentValue){
      var existingObj = previousValue.find(function(obj){
          return obj._id == currentValue._id;
      });

      if(existingObj){
          Object.assign(existingObj, currentValue);
          existingObj.total = +(existingObj.M) + +(existingObj.S);
      }else{
          if(currentValue.M){
                currentValue.total = currentValue.M;
          }else if(currentValue.S){
              currentValue.total = currentValue.S;
          }
          previousValue.push(currentValue);
      }
     return previousValue; 
},[]);

答案 4 :(得分:0)

这是一个非常简洁的lodash解决方案:

_(data).groupBy("_id").map((group, id) => { //group is an array of items with the same id
    const mTotal = _.sum(_.map(group, (item) => parseInt(item.M) || 0));
    const sTotal = _.sum(_.map(group, (item) => parseInt(item.S) || 0));
    return {
         _id: id,
         M: mTotal.toString(),
         S: sTotal.toString(),
         Total: (mTotal + sTotal).toString()
    }
}).value() //End lodash chain

旁注:通过不将字符串转换为数字,你会让事情变得更难。