2013-08-18 67 views
0

我有一个json,其数组被称为chargeamountunitLevel。我想由chargeAmountUnit.The输入JSON分组总结行动的chargeAmount:如何使用节点-js使用聚合函数

"chargeamountunitLevel": [ 
     { 
      "chargeAmount": 4, 
      "chargeAmountUnit": "per hour", 
      "currencyCode": "USD" 
     }, 
     { 
      "chargeAmount": 50, 
      "chargeAmountUnit": "per hour", 
      "currencyCode": "USD" 
     }, 
     { 
      "chargeAmount": 25, 
      "chargeAmountUnit": "per month", 
      "currencyCode": "USD" 
     }, 
     { 
      "chargeAmount": 25, 
      "chargeAmountUnit": "per month", 
      "currencyCode": "USD" 
     } 

    ] 

结果可能如下:

"chargeamountunitLevel": [ 
     { 
      "chargeAmount": 54, 
      "chargeAmountUnit": "per hour", 
      "currencyCode": "USD" 
     }, 
     { 
      "chargeAmount": 50, 
      "chargeAmountUnit": "per month", 
      "currencyCode": "USD" 
     } 

     ] 

有什么建议?

回答

2

你总是可以利用reduce功能。因为我们提供了initialValue作为reduce的第二个参数,所以第一次调用callback时,该值将作为result参数传递。然后对于所有后续呼叫,result将成为先前呼叫的返回值。

这里我们基本上检查我们的initialValue对象,如果chargeAmountUnito已经存在作为一个关键。如果没有,我们创建一个具有相同属性值的对象o的新对象,并使用chargeAmountUnit作为关键字将其放入我们的initialValue对象中。但是,如果它确实存在,我们使用chargeAmountUnit作为关键字检索先前创建的对象,并简单地总结相关的值。

此外,您可能已经注意到,我们正在推动在一个阵列中创建的对象,这是因为在最后,你想数组作为一个结果,而不是像这样:

{ 
    'per month': {...}, 
    'per hour': {...} 
} 

这里是如何做到这一点:

data.reduce(function (result, o) { 
    var unit = o.chargeAmountUnit; 
    if (!(unit in result)) { 
     result.arr.push(result[unit] = { 
      chargeAmountUnit: unit, 
      chargeAmount: o.chargeAmount, 
      currencyCode: o.currencyCode 
     }); 
    } else { 
     result[unit].chargeAmount += o.chargeAmount; 
    } 

    return result; 
}, { arr: [] }).arr; 

编辑:由多个字段组,你可以简单地通过key由场字符串值concanating组创建一个组。

以下将分组在chargeAmountUnitcurrencyCode

data.reduce(function (result, o) { 
    //compute group by key 
    var key = o.chargeAmountUnit + o.currencyCode; 
    if (!(key in result)) { 
     result.arr.push(result[key] = { 
      chargeAmountUnit: o.chargeAmountUnit, 
      chargeAmount: o.chargeAmount, 
      currencyCode: o.currencyCode 
     }); 
    } else { 
     result[key].chargeAmount += o.chargeAmount; 
    } 

    return result; 
}, { arr: [] }).arr; 
+0

由你工作的好方法,但不能理解为什么我在结果中得到重复值 – Prem

+0

@Prem,你能举个例子吗? – plalx

+0

我已解决获取重复项(我在console.log(结果)重复,但主要的事情,我不能从谷歌得到它是如何修改您的代码,如果我想通过基于chargeAmountUnit和currencyCode分组。 – Prem

1

可以使用underscore.js

这里是代码:

var _ = require('underscore'); // use `npm install underscore` 
var util = require('util');  // nodejs default modules 

var data = { 
    "chargeamountunitLevel": [{ 
    "chargeAmount": 4, 
    "chargeAmountUnit": "per hour", 
    "currencyCode": "USD" 
    } 
    , { 
    "chargeAmount": 50, 
    "chargeAmountUnit": "per hour", 
    "currencyCode": "USD" 
    } 
    , { 
    "chargeAmount": 25, 
    "chargeAmountUnit": "per month", 
    "currencyCode": "USD" 
    } 
    , { 
    "chargeAmount": 10, 
    "chargeAmountUnit": "per month", 
    "currencyCode": "USD" 
    } 
    , { 
    "chargeAmount": 1, 
    "chargeAmountUnit": "per month", 
    "currencyCode": "RMB" 
    } 
    , { 
    "chargeAmount": 25, 
    "chargeAmountUnit": "per month", 
    "currencyCode": "HKD" 
    }] 
}; 

// This should give you an array of objects that 
// are grouped by chargeAmountUnit. 
var tmp = _.groupBy(data["chargeamountunitLevel"], function(d){ 
    return d["chargeAmountUnit"]; 
}); 
// Show the temporary result :o) 
console.log(tmp); 

// Now group the result with currency code 
var tmp2 = {}; 
_.each(tmp, function(t, unit){ 
    tmp2[unit] = _.groupBy(t, function(d){ 
    return d["currencyCode"]; 
    }); 
}); 

// show the temp result again 
console.log("tmp2: \n" + util.inspect(tmp2, false, null, true)); // util.inspect() is different in node v0.10.x 

var finalResult = []; 
_.each(tmp2, function(t, unit){ 
    _.each(t, function(items, currency){ 
    var total = 0; 
    _.each(items, function(item){ 
     total += item["chargeAmount"];  // should also * currencyCode? 
    }); 
    finalResult.push({ 
     "chargeAmountUnit" : unit 
     , "chargeAmount" : total 
     , "currencyCode" : currency // Update it yourself :o) 
    }); 
    }); 
}); 

console.log(finalResult); 
+0

太好了。你的代码运行良好。如何通过chargeAmountUnit和currencycode将chargeAmount分组。因为我需要显示没有硬编码的货币代码。 (即使货币代码在数组中的所有值上都是统一的) – Prem

+0

@Prem,请注意,即使在我的答案中,它只是在'chargeAmountUnit',而不是'currencyCode'上分组,然而它很容易修复它。你只需要计算一个新的'key'。而不是仅限于'chargeAmountUnit',它将是'chargeAmountUnit'和'currencyCode'的连接。 – plalx

+0

我同意@plalx所说的。您可以通过连接'chargeAmountUnit'和'currencyCode'(例如''per month | HKD')来创建一个新的“钥匙”。但我认为它不如使用两个groupBy()那样优雅和“麻烦”。 –