循环遍历对象数组,并按对象元素id返回每个总值的总和

我正在为一个非常复杂的发票方法计算税金 。 我不能解释整个过程,但如果你有问题,我会尽我所能回答。

我在JS中提出了一个对象数组:

[ {row_id: "20003859", expense_id: "429", tax_select: "tax1", tax_id: "1", tax_name: "GST 5%", tax_no: "", tax_value: "13.23"}, {row_id: "20003859", expense_id: "429", tax_select: "tax2", tax_id: "3", tax_name: "QST 9.975%", tax_no: "", tax_value: "26.38"}, {row_id: "20003840", expense_id: "409", tax_select: "tax1", tax_id: "1", tax_name: "GST 5%", tax_no: "", tax_value: "13.23"}, {row_id: "20003840", expense_id: "409", tax_select: "tax2", tax_id: "3", tax_name: "QST 9.975%", tax_no: "", tax_value: "26.38"}, {row_id: "20003870", expense_id: "419", tax_select: "tax1", tax_id: "2", tax_name: "HST 13%", tax_no: "", tax_value: "34.39"} ] 

正如你所看到的,我有3个tax_ids:1,2和3.我可以有很多但是为了简单起见我只放了3个。

我需要循环遍历这个对象数组,并提出另一个对象数组,其中包含 tax_id的总数:

 [ {tax_name: "GST 5%", total_tax: sum of tax_value for tax_id = 1}, {tax_name: "QST 9.975%", total_tax: sum of tax_value for tax_id = 3}, {tax_name: "HST 13%", sum of tax_value for tax_id = 2} ] 

之后,我可以遍历此数组并显示每个税的总计,添加小计并显示总发票。

另外,我应该通过tax_select对它们进行排序,但这是我可以忍受的事情。

我试过:其中selected_taxes是第一个对象数组

  for (i = 0; i < selected_taxes.length; i++){ var sum = 0; $.each( selected_taxes[i], function( tax_id, tax_value ) { sum += tax_value; }); console.log(sum); } 

但没有运气。

非常感谢您的帮助或建议。

我认为Array.prototype.reduce将是你最好的选择:

 var totals = data.reduce(function(c,x){ if(!c[x.tax_id]) c[x.tax_id] = { tax_name: x.tax_name, tax_id: x.tax_id, total_tax: 0 }; c[x.tax_id].total_tax += Number(x.tax_value); return c; }, {}); 

此方法生成一个对象,该对象具有税号ID作为其属性。 如果你真的想要一个平面数组,你可以在事后将其转换为数组:

 var totalsArray = []; for(var taxId in totals){ totalsArray.push(totals[taxId]): } 

演示: http : //jsfiddle.net/3jaJC/1/

当你循环遍历对象时,查看它是什么taxId并为每个不同的taxId生成一个总和。

 var sums = {}, obj, i; for (i = 0; i < selected_taxes.length; i++){ obj = selected_taxes[i]; if (!sums[obj.tax_id]) { sums[obj.tax_id] = 0; } sums[obj.tax_id] += +obj.tax_value; } console.log(sums); //{ 1:26.46, 2:34.39, 3: 52.76} 

http://jsfiddle.net/4X6Wb/

使用reduce方法:

 selected_taxes.reduce(function (p, c) { if (p[c["tax_id"]]) { p[c["tax_id"]]["total_tax"] += +c["tax_value"]; } else { p[c["tax_id"]] = { "tax_name": c["tax_name"], "total_tax": +c["tax_value"] } } return p; }, {}); 

这将返回包含所需数据的新对象:

 { "1": { "tax_name": "GST 5%", "total_tax": 26.46 }, "2": { "tax_name": "HST 13%", "total_tax": 34.39 }, "3": { "tax_name": "QST 9.975%", "total_tax": 52.76 } } 

DEMO

我使用类型化数组的解决方案:

var sum_arr = new Float32Array(arr.length); for (var i = 0; i < arr.length; i++){ var tax_id = arr[i].tax_id; sum_arr[tax_id] += parseFloat(arr[i].tax_value); }

jsfidle: http : //jsfiddle.net/LJ7Nd/

想法:假设你有n个tax_ids。 创建一个名为sum_arr的长度为n的数组。 在每次迭代时拉出tax_id,并通过相应的tax_value递增数组中的特定插槽。 然后,当您想要tax_id = 1的所有tax_values的总和时,您只需索引sum_arr [1]。