ES6 Reduce nested objects in an array

Viewed 9165

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!

4 Answers
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);
Related