Reputation: 623
I've been using map and reduce over some objects and arrays which have been working well so far, however I'm having trouble with one array.
Example of data here:
var arr =
[
[
{
"id": 6501511,
"invoiceId": {
"id": 1043773
},
"chargeBandType": "TIME",
"jobTaskId": {
"id": 19399852
},
"invoicedNet": {
"amountString": 0,
"currencyType": "USD"
},
"invoicedTaxOneOtherCurrency": null,
"invoicedTaxOne": {
"amountString": 0,
"currencyType": "USD"
},
"taxOneRate": 0.1
},
{
"id": 6501517,
"invoiceId": {
"id": 1043773
},
"chargeBandType": "TIME",
"jobTaskId": null,
"jobExpenseId": null,
"jobThirdPartyCostId": {
"id": 20602
},
"invoicedNet": {
"amountString": 0,
"currencyType": "USD"
},
"invoicedTaxOneOtherCurrency": null,
"invoicedTaxOne": {
"amountString": 0,
"currencyType": "USD"
},
"taxOneRate": 0.1
},
{
"id": 6501508,
"invoiceId": {
"id": 13773
},
"chargeBandType": "TIME",
"jobTaskId": {
"id": 19398574
},
"invoicedNet": {
"amountString": 30,
"currencyType": "USD"
},
"invoicedTaxOneOtherCurrency": null,
"invoicedTaxOne": {
"amountString": 3,
"currencyType": "USD"
},
"taxOneRate": 0.1
},
{
"id": 65014,
"invoiceId": {
"id": 104
},
"chargeBandType": "TIME",
"jobTaskId": null,
"jobExpenseId": null,
"jobThirdPartyCostId": {
"id": 206
},
"invoicedNet": {
"amountString": 0,
"currencyType": "USD"
},
"invoicedTaxOneOtherCurrency": null,
"invoicedTaxOne": {
"amountString": 0,
"currencyType": "USD"
},
"taxOneRate": 0.1
}],
[
{
"id": 6483,
"invoiceId": {
"id": 1042400
},
"chargeBandType": "TIME",
"jobTaskId": {
"id": 198574
},
"invoicedNet": {
"amountString": 100,
"currencyType": "USD"
},
"invoicedTaxOneOtherCurrency": null,
"invoicedTaxOne": {
"amountString": 10,
"currencyType": "USD"
},
"taxOneRate": 0.1
}
]
];
I am trying to reduce the values of invoicedNet.amountString, which would bring a sum of 130 in the case above.
I have tried many ways to work this, including functions similar to the below:
var sum = arr.reduce(function(a, b) {
return a += b.invoicedNet.amountString;
}, 0);
However, no matter how I try this, I keep getting the error:
TypeError: Cannot read property 'amountString' of undefined
(It seems to pick up b.invoicedNet as an object though).
Could anyone suggest an approach to this?
Thanks!
Upvotes: 5
Views: 13760
Reputation: 480
var sum = arr.reduce(function(a, b) {
return a += b.invoicedNet.amountString;
}, 0);
The above code doesn't work because arr is a multidimensional array. Its elements are also an array. You need a nested reducer for this type of array. with the arrow function, it can be written as -
const total = arr.reduce((sum, tasks) => tasks.reduce((previousSum, task) =>
previousSum + task.invoicedNet.amountString, sum) , 0);
Upvotes: 0
Reputation: 36511
Flatten your array, then reduce:
[].concat(...arr).reduce((a, { invoicedNet: { amountString }}) => a + amountString, 0)
var arr =
[
[
{
"id": 6501511,
"invoiceId": {
"id": 1043773
},
"chargeBandType": "TIME",
"jobTaskId": {
"id": 19399852
},
"invoicedNet": {
"amountString": 0,
"currencyType": "USD"
},
"invoicedTaxOneOtherCurrency": null,
"invoicedTaxOne": {
"amountString": 0,
"currencyType": "USD"
},
"taxOneRate": 0.1
},
{
"id": 6501517,
"invoiceId": {
"id": 1043773
},
"chargeBandType": "TIME",
"jobTaskId": null,
"jobExpenseId": null,
"jobThirdPartyCostId": {
"id": 20602
},
"invoicedNet": {
"amountString": 0,
"currencyType": "USD"
},
"invoicedTaxOneOtherCurrency": null,
"invoicedTaxOne": {
"amountString": 0,
"currencyType": "USD"
},
"taxOneRate": 0.1
},
{
"id": 6501508,
"invoiceId": {
"id": 13773
},
"chargeBandType": "TIME",
"jobTaskId": {
"id": 19398574
},
"invoicedNet": {
"amountString": 30,
"currencyType": "USD"
},
"invoicedTaxOneOtherCurrency": null,
"invoicedTaxOne": {
"amountString": 3,
"currencyType": "USD"
},
"taxOneRate": 0.1
},
{
"id": 65014,
"invoiceId": {
"id": 104
},
"chargeBandType": "TIME",
"jobTaskId": null,
"jobExpenseId": null,
"jobThirdPartyCostId": {
"id": 206
},
"invoicedNet": {
"amountString": 0,
"currencyType": "USD"
},
"invoicedTaxOneOtherCurrency": null,
"invoicedTaxOne": {
"amountString": 0,
"currencyType": "USD"
},
"taxOneRate": 0.1
}],
[
{
"id": 6483,
"invoiceId": {
"id": 1042400
},
"chargeBandType": "TIME",
"jobTaskId": {
"id": 198574
},
"invoicedNet": {
"amountString": 100,
"currencyType": "USD"
},
"invoicedTaxOneOtherCurrency": null,
"invoicedTaxOne": {
"amountString": 10,
"currencyType": "USD"
},
"taxOneRate": 0.1
}
]
];
console.log([].concat(...arr).reduce((a, { invoicedNet: { amountString }}) => a + amountString, 0))
Upvotes: 1
Reputation: 1380
You can do this quite neatly by flattening the arrays first and then reducing:
[].concat(...arr)
.map(invoice => invoice.invoicedNet.amountString)
.reduce((a, b) => a + b)
Upvotes: 2
Reputation: 386550
You need to loop both arrays.
var arr = [[{ id: 6501511, invoiceId: { id: 1043773 }, chargeBandType: "TIME", jobTaskId: { id: 19399852 }, invoicedNet: { amountString: 0, currencyType: "USD" }, invoicedTaxOneOtherCurrency: null, invoicedTaxOne: { amountString: 0, currencyType: "USD" }, taxOneRate: 0.1 }, { id: 6501517, invoiceId: { id: 1043773 }, chargeBandType: "TIME", jobTaskId: null, jobExpenseId: null, jobThirdPartyCostId: { id: 20602 }, invoicedNet: { amountString: 0, currencyType: "USD" }, invoicedTaxOneOtherCurrency: null, invoicedTaxOne: { amountString: 0, currencyType: "USD" }, taxOneRate: 0.1 }, { id: 6501508, invoiceId: { id: 13773 }, chargeBandType: "TIME", jobTaskId: { id: 19398574 }, invoicedNet: { amountString: 30, currencyType: "USD" }, invoicedTaxOneOtherCurrency: null, invoicedTaxOne: { amountString: 3, currencyType: "USD" }, taxOneRate: 0.1 }, { id: 65014, invoiceId: { id: 104 }, chargeBandType: "TIME", jobTaskId: null, jobExpenseId: null, jobThirdPartyCostId: { id: 206 }, invoicedNet: { amountString: 0, currencyType: "USD" }, invoicedTaxOneOtherCurrency: null, invoicedTaxOne: { amountString: 0, currencyType: "USD" }, taxOneRate: 0.1 }], [{ id: 6483, invoiceId: { id: 1042400 }, chargeBandType: "TIME", jobTaskId: { id: 198574 }, invoicedNet: { amountString: 100, currencyType: "USD" }, invoicedTaxOneOtherCurrency: null, invoicedTaxOne: { amountString: 10, currencyType: "USD" }, taxOneRate: 0.1 }]],
sum = arr.reduce(function (a, b) {
b.forEach(function (c) {
a += c.invoicedNet.amountString;
});
return a;
}, 0);
console.log(sum);
Upvotes: 6