I want to dynamically add new attribute to all of the items in an array using map. But while adding it to each item, the value of this attribute is the sum of all previous items newly added attribute
Consider this example :
let persons = [{
"name": "A",
"salary": 2
}, {
"name": "B",
"salary": 5
},{
"name":"C",
"salary":12
}];
I want to return :
[{
"name": "A",
"salary": 2,
"sumSalary":2
}, {
"name": "B",
"salary": 5,
"sumSalary":7
},{
"name":"C",
"salary":12,
"sumSalary":19
}];
I've tried this one:
let mutatedPersons = persons.map((currentValue, index, mutatedPersons) => ({
...currentValue,
sumSalary: currentValue.name === 'A' ? currentValue.salary : mutatedPersons[index - 1].sumSalary + currentValue.salary
}))
but i keep getting this :
[
0: {name: "A", salary: 2, sumSalary: 2}
1: {name: "B", salary: 5, sumSalary: NaN}
2: {name: "C", salary: 12, sumSalary: NaN}
]
The mutatedPersons
you refer to is the original array (see map's parameters), and not the updated array, which doesn't actually exist before the map end. You can cache the previous sum in an external variable (prevSumSalary
), and use it as the basis of the new one:
const persons = [{ name: "A", salary: 2 }, { name: "B", salary: 5 }, { name: "C", salary: 12 }]
let prevSumSalary = 0;
const mutatedPersons = persons.map((currentValue, index) => ({
...currentValue,
sumSalary: (prevSumSalary = prevSumSalary + currentValue.salary)
}))
console.log(mutatedPersons);
Another option is to use Array.reduce()
, since you have access to the accumulated values:
const persons = [{ name: "A", salary: 2 }, { name: "B", salary: 5 }, { name: "C", salary: 12 }]
const mutatedPersons = persons.reduce((r, currentValue) => [...r,
({
...currentValue,
sumSalary: currentValue.salary + (r.length && r[r.length - 1].sumSalary)
})
], [])
console.log(mutatedPersons);