Reputation: 623
I'm returning JSON data from an API. I am then using map to create my own object.
The data has multiple objects. Here is an example:
{
"data": {
"job": [
{
"jobNumber": "1",
"jobTasks": {
"jobTask": [
{
"total": { "amountString": "10.00" }
},
{
"total": { "amountString": "10.00" }
}
]
}
},
{
"jobNumber": "2",
"jobTasks": {
"jobTask": [
{
"total": { "amountString": "20.00" }
},
{
"total": { "amountString": "20.00" }
}
]
}
},
{
"jobNumber": "3",
"jobTasks": {
"jobTask": [
{
"total": { "amountString": "30.00" }
},
{
"total": { "amountString": "30.00" }
}
]
}
}
]
}
}
As from that returned example, I want to have the following:
jobNumber: 1: Total 20. jobNumber: 2: Total 40. jobNumber: 3: Total 60.
Here is the code I am using:
var array = response.data.map(function(item, array) {
var sumTaskTotal = item.jobTasks.reduce(function(sumTaskTotal, item, index) {
if (item !== null && item.total !== null) {
sumTaskTotal += item.total.amountString;
return sumTaskTotal;
}
}, 0);
array = response.data.map(item => ({
jobNumber: item.jobNumber,
sumTaskTotal: sumTaskTotal,
}));
}
However the sum I am using just keeps summing, so I end up with:
jobNumber: 1: Total 120. jobNumber: 120: Total 120. jobNumber: 3: Total 120.
I have tried for loops but that doesn't seem to get me anywhere.
Upvotes: 1
Views: 75
Reputation: 4526
you can use just forEach
to get your desired string.
const data = {
"data": {
"job": [
--
]
}
}
let string = "";
data.data.job.forEach((item) => {
const sum = item.jobTasks.jobTask.reduce((total, i) => parseFloat(i.total.amountString) + total, 0);
string += `jobNumber: ${item.jobNumber}: Total ${sum}. `;
});
console.log(string);
there will be a unnecessary space after your string. use trim function if necessary.
Upvotes: 0
Reputation: 4568
Not actually sure how you got jobNumber: 1: Total 120. jobNumber: 120: Total 120. jobNumber: 3: Total 120.
. I tried your code and when you log the array, you'd just get an array with 3 undefined items
; each iteration in the map
in your code doesn't return anything that's why the array contains 3 undefined items.
Also, data
and jobTasks
are objects. You should use map
or reduce
on the job
and jobTask
properties.
As for adding the totals, amountString
is a string
(obviously), and you should convert it into a number first. Otherwise, the result in your first iteration would be 010.00
since you're concatenating a string
to a number
. It's not adding 0
and 10.00
.
The array = response.data.map...
part in your outer map would just go through all the jobs again. Each iteration in map
expects an item to be returned. If you don't return anything, undefined
will the value of that array. So instead of mapping the array again, you could just do this:
return {
jobNumber: item.jobNumber,
sumTaskTotal,
};
That would then result in an array with 3 objects:
[{
jobNumber: '1',
sumTaskTotal: 20,
}, {
jobNumber: '2',
sumTaskTotal: 40,
}, {
jobNumber: '3',
sumTaskTotal: 60,
}]
But, you can do a nested reduce
instead:
const formatted = response.data.job.reduce((prevString, currentJob) => {
const total = currentJob.jobTasks.jobTask.reduce((prevTotal, currentJobTask) => {
return prevTotal + Number(currentJobTask.total.amountString);
}, 0);
return `${prevString}jobNumber: ${currentJob.jobNumber}: Total ${total}. `;
}, '');
const response = {
"data": {
"job": [{
"jobNumber": "1",
"jobTasks": {
"jobTask": [{
"total": {
"amountString": "10.00"
}
}, {
"total": {
"amountString": "10.00"
}
}]
}
}, {
"jobNumber": "2",
"jobTasks": {
"jobTask": [{
"total": {
"amountString": "20.00"
}
}, {
"total": {
"amountString": "20.00"
}
}]
}
}, {
"jobNumber": "3",
"jobTasks": {
"jobTask": [{
"total": {
"amountString": "30.00"
}
}, {
"total": {
"amountString": "30.00"
}
}]
}
}]
}
};
const formatted = response.data.job.reduce((prevString, currentJob) => {
const total = currentJob.jobTasks.jobTask.reduce((prevTotal, currentJobTask) => {
return prevTotal + Number(currentJobTask.total.amountString);
}, 0);
return `${prevString}jobNumber: ${currentJob.jobNumber}: Total ${total}. `;
}, '');
console.log(formatted.trim());
Upvotes: 1