Reputation: 21
hope that you're doing well. I've a question related to the .reduce function. I'm refactoring an elder code and, in order to fulfill the DRY principle, I'd like to know how to create a function that allows my to achieve a 'simple' process from .reduce:
phoNumbId
in the example).mount
).To clarify my question, I've this example dictionary:
const nexus = [
{ namesId: 1, phoNumbId: 1, country: 'PERU', mount: 1200 },
{ namesId: 1, phoNumbId: 2, country: 'CANADA', mount: 2000},
{ namesId: 2, phoNumbId: 2, country: 'ENGLAND', mount: 3000},
{ namesId: 2, phoNumbId: 3, country: 'RUSSIA', mount: 40000},
{ namesId: 3, phoNumbId: 1, country: 'BELGIUM', mount: 500},
{ namesId: 3, phoNumbId: 2, country: 'SPAIN', mount: 500},
{ namesId: 3, phoNumbId: 3, country: 'PORTUGAL', mount: 2020}
]
And the (coded) process that I want to refactor is:
var result2 = [];
nexus.reduce(function (res, value) {
if (!res[value.phoNumbId]) {
res[value.phoNumbId] = { phoNumbId: value.phoNumbId, mount: 0 };
result2.push(res[value.phoNumbId])
}
res[value.phoNumbId].mount+= value.mount;
return res;
}, {});
The way that my limited knowledge in JS allows me to code a possible solution then is as follows:
function sumAll(firstValue,secondValue,finalArray){
if (!res[value.firstValue]) {
res[value.firstValue] = { firstValue: value.firstValue, secondValue: 0 };
finalArray.push(res[value.firstValue])
}
res[value.primerValor].secondValue+= value.secondValue;
return res;
}
var result2 = [];
nexus.reduce(function (res, value) { sumAll(phoNumbId,mount,result2) }, {});
I'd really appreciate anykind of help :) P.S.: I couldn't think of another title for the question, feel that doesn't summarize the real problem. I accept suggestions.
Upvotes: 1
Views: 219
Reputation: 2932
Consider your original code (before refactoring) is runnable.
Here is the first integration:
var result2 = nexus.reduce(function (res, value) {
if (!res[value.phoNumbId]) {
res[value.phoNumbId] = { phoNumbId: value.phoNumbId, mount: 0 };
res.push(res[value.phoNumbId])
}
res[value.phoNumbId].mount += value.mount;
return res;
}, []);
What changed:
reduce
function is assigned directly to result2
reduce
function is the initial value of the result2
from the origin (in this case, an empty array []
)result2.push(....)
is changed to res.push(....)
Here is the second integration:
var result = nexus.reduce(function (acc, cur) {
if (!acc[cur.phoNumbId]) {
acc[cur.phoNumbId] = { phoNumbId: cur.phoNumbId, mount: 0 };
acc.push(acc[cur.phoNumbId])
}
acc[cur.phoNumbId].mount += cur.mount;
return acc;
}, []);
What changed:
result2
-> result
res
-> acc
(it stands for accumulator
)value
-> cur
(it stands for current value
)Here is the third integration
function my_reducer(acc, cur) {
if (!acc[cur.phoNumbId]) {
acc[cur.phoNumbId] = { phoNumbId: cur.phoNumbId, mount: 0 };
acc.push(acc[cur.phoNumbId])
}
acc[cur.phoNumbId].mount += cur.mount;
return acc;
}
var result = nexus.reduce(my_reducer, []);
What changed:
no name
function (the one that was passed as the 1st param to the reduce
function) to a function with a name.It will take time to explain the way the reduce
function works. You can find out around the internet or other StackOverflow questions/answers.
Here is a short explanation:
Take a look at var result = nexus.reduce(my_reducer, []);
, consider
result
is a soup bowl π₯nexus
is an array of ingredients [π₯© meat, πΌ milk, π₯ egg, π
tomato, π₯ potato]reduce
is a cook π§βπ³my_reducer
is a cooker robot π€[]
is an empty bow π₯£Then 2 params pass to the my_reducer
(the cooker robot π€) are:
acc
: the current status of the bowl π₯£cur
: the current ingredient we are processingThus
var result = nexus.reduce(my_reducer, []);
similar to
π₯ = [π₯©, πΌ, π₯, π , π₯].π§βπ³(π€, π₯£)
π€(current bowl status, current ingredient)
+ the soup bowl π₯ is created by using a cooker π€
+ to cook all ingredients [π₯©, π₯, πΌ, π
, π₯]
+ that prepared by the cook π§βπ³
+ start with an empty bowl π₯£
How it works:
At the beginning, you have: a cook π§βπ³, a cooker robot π€, an empty bow π₯£
π§βπ³(π€, π₯£)
The cook π§βπ³ will loop through each ingredient (follow the order in the array)
so on
The last ingredient is potato π₯
That is our soup π₯
Upvotes: 1
Reputation: 63524
You can use computed property names - that's using your argument values in bracket notation - to create the object.
const data=[{namesId:1,phoNumbId:1,country:"PERU",mount:1200},{namesId:1,phoNumbId:2,country:"CANADA",mount:2e3},{namesId:2,phoNumbId:2,country:"ENGLAND",mount:3e3},{namesId:2,phoNumbId:3,country:"RUSSIA",mount:4e4},{namesId:3,phoNumbId:1,country:"BELGIUM",mount:500},{namesId:3,phoNumbId:2,country:"SPAIN",mount:500},{namesId:3,phoNumbId:3,country:"PORTUGAL",mount:2020}];
function sumAll(data, first, second) {
const temp = data.reduce((acc, c) => {
// For convenience assign the object key
// to the first argument
const key = c[first];
// If the key doesn't exist on the object
// add it and assign an object to it
acc[key] ??= { [first]: key, [second]: 0 };
// Then update the value
acc[key][second] += c[second];
return acc;
}, {});
// Finally you probably want to return
// an array of just those objects
return Object.values(temp);
}
console.log(sumAll(data, 'phoNumbId', 'mount'));
console.log(sumAll(data, 'namesId', 'mount'));
Additional documentation
Upvotes: 3