This is what I have:
const arrayA = [{name:'a', amount: 10, serviceId: '23a', test:'SUCCESS'},
{name:'a', amount: 9, test:'FAIL'},
{name:'b', amount: 15, serviceId: '23b', test:'SUCCESS'}]
(note that there's object not having 'serviceId')
I would like to get:
[{name:'a', amount: 19, test:'FAIL'},
{name:'b', amount: 15, test:'SUCCESS'}]
- I want to sum
amount
field grouped by name. - 'test' field should be
FAIL
if there's any object with the valueFAIL
(grouped by name) - I don't care about the value of
serviceId
and don't want to include it in the new object.
I have searched, and tried something like this: (reference: )
const result = Object.values(arrayA.reduce((r, o) => (r[o.name]
? (r[o.name].amount += o.amount)
: (r[o.name] = {...o}), r), {}));
but still not sure how to assign test
field.
Any help would be appreciated!
This is what I have:
const arrayA = [{name:'a', amount: 10, serviceId: '23a', test:'SUCCESS'},
{name:'a', amount: 9, test:'FAIL'},
{name:'b', amount: 15, serviceId: '23b', test:'SUCCESS'}]
(note that there's object not having 'serviceId')
I would like to get:
[{name:'a', amount: 19, test:'FAIL'},
{name:'b', amount: 15, test:'SUCCESS'}]
- I want to sum
amount
field grouped by name. - 'test' field should be
FAIL
if there's any object with the valueFAIL
(grouped by name) - I don't care about the value of
serviceId
and don't want to include it in the new object.
I have searched, and tried something like this: (reference: https://stackoverflow./a/50338360/13840216)
const result = Object.values(arrayA.reduce((r, o) => (r[o.name]
? (r[o.name].amount += o.amount)
: (r[o.name] = {...o}), r), {}));
but still not sure how to assign test
field.
Any help would be appreciated!
Share Improve this question edited Dec 3, 2020 at 9:15 tadman 212k23 gold badges236 silver badges265 bronze badges asked Dec 3, 2020 at 9:15 amu03amu03 3813 silver badges19 bronze badges5 Answers
Reset to default 5You need to check test
and update the value, if necessary.
const
array = [{ name: 'a', amount: 10, serviceId: '23a', test: 'SUCCESS' }, { name: 'a', amount: 9, test: 'FAIL' }, { name: 'b', amount: 15, serviceId: '23b', test: 'SUCCESS' }],
result = Object.values(array.reduce((r, { name, amount, test }) => {
if (!r[name]) r[name] = { name, amount: 0, test };
r[name].amount += amount;
if (test === 'FAIL') r[name].test = 'FAIL';
return r;
}, {}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
This? Just test if the .test is already fail
const arrayA = [{ name: 'a', amount: 10, serviceId: '23a', test: 'SUCCESS' }, { name: 'a', amount: 9, test: 'FAIL' }, { name: 'b', amount: 15, serviceId: '23b', test: 'SUCCESS' }],
result = Object.values(
arrayA.reduce((r, o) => {
r[o.name] ? (r[o.name].amount += o.amount) : (r[o.name] = { ...o })
r[o.name].test = r[o.name].test === "FAIL" ? "FAIL" : o.test;
return r;
}, {})
);
console.log(result);
Store the sums and final values in an object and then convert them into an array.
const arrayA = [
{ name: "a", amount: 10, serviceId: "23a", test: "SUCCESS" },
{ name: "a", amount: 9, test: "FAIL" },
{ name: "b", amount: 15, serviceId: "23b", test: "SUCCESS" },
];
const map = {};
arrayA.forEach((row) => {
if (!map[row.name]) {
map[row.name] = { name: row.name, amount: 0, test: "SUCCESS" };
}
map[row.name].amount += row.amount;
if (row.test === "FAIL") {
map[row.name].test = "FAIL";
}
});
const result = Object.values(map);
console.log(result);
That is a nice use case of how to process data in js, particularly how functions like map
and reduce
can help you do that processing. Which are a nice alternative to loops and iterations.
Moreover, I'd advise you to do the processing in steps, as you have defined in the description. For example:
const arrayA = [
{name:'a', amount: 10, serviceId: '23a', test:'SUCCESS'},
{name:'a', amount: 9, test:'FAIL'},
{name:'b', amount: 15, serviceId: '23b', test:'SUCCESS'}
]
// First group the items by name
const byName = arrayA.reduce((ob, item) => {
if(!(item.name in ob))
ob[item.name] = []
ob[item.name].push({amount: item.amount, test: item.test})
return ob
}, {})
// Then pute the total amount in each group and find if there is any FAIL in a group
const sumByName = Object.keys(byName).map(name => { // This is a way to iterate through the groups
// Sum the amount in all elements of a group
const amount = byName[name].reduce((sum, item) => sum + item.amount , 0)
// Find if there is any FAIL in a group
const test = byName[name].map(item => item.test) // Get an array with only the test string
.includes('FAIL') ? 'FAIL': 'SUCCESS' // Evaluate if the array includes FAIL
return ({name, amount, test})
})
console.log(sumByName)
Finally, I'd advise you to watch these videos on map and reduce (and all the content of that channel for this matter)
- Reduce
- Map
you can use Array.reduce
method:
const arrayA=[{name:"a",amount:10,serviceId:"23a",test:"SUCCESS"},{name:"a",amount:9,test:"FAIL"},{name:"b",amount:15,serviceId:"23b",test:"SUCCESS"}];
let result = arrayA.reduce((aac,{name,amount,test}) => {
let idx = aac.findIndex(n => n.name === name)
if( idx != -1){
aac[idx].amount += amount;
if(test === "FAIL")
aac[idx].test = "FAIL"
return aac
}
aac.push({name,amount,test})
return aac
},[])
console.log(result);
console.log(arrayA)