2013-08-18 112 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()那樣優雅和「麻煩」。 –