5

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!

0

4 Answers 4

6

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);

Sign up to request clarification or add additional context in comments.

Comments

2

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)

2 Comments

I'm not one for premature optimization, but your mapping is really not necessary - why do two loops when one will suffice?
Just find it to be neater. It's clearer that you are extracting that value and then summing.
1

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))

Comments

0
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);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.