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!

asked Aug 4, 2017 at 18:20
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);

answered Aug 4, 2017 at 18:25
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)
answered Aug 4, 2017 at 18:27

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

answered Aug 4, 2017 at 18:28

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);
answered Jul 2, 2022 at 4:46

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.