Reputation: 2760
I have an array of objects that denotes running status of some processes over time.
[
{ process: 'first' , running:true}, // starting 'first'
{ process: 'second', running:true}, // starting 'second'
{ process: 'first' , running:true}, // starting 'first' again
{ process: 'second', running:false}, // stopping 'second'
{ process: 'first' , running:false} // stopping 'first' ( there is one more running which is not yet stopped)
]
I would like to group this array by process and provide the current running status. Expected output,
{
'first' : true, // started two times but stopped only once. So there one more running
'second' : false // started and stopped once
}
What I did is to group this object array into a single object like,
{
'first': [true,true,false],
'second': [true,false]
}
code,
arr.reduce((acc, item) => {
const key = item.process;
if (!acc[key]) acc[key] = [];
acc[key].push(item.running);
return acc;
}, {});
Is there any elegant way now to achieve my target from this state?
Upvotes: 2
Views: 63
Reputation: 1700
I would do in one go. One variable for counting flags (true +1, false -1) and one response.
arr.reduce((acc, item, index) => {
const key = item.process;
if (!acc.flag) //used to remove those properties easily later.
acc.flag = {}
if (!acc[key]) {
acc.flag[`${key}_count`] = 0
acc[key] = false;
}
acc.flag[`${key}_count`] += item.running ? 1 : -1;
acc[key] = !!acc.flag[`${key}_count`];
if(index === arr.length -1) // last iteration
delete acc.flag
return acc;
}, {});
Upvotes: 1
Reputation: 386560
You could count running flags and get a result of the boolean value.
const
data = [{ process: 'first' , running: true }, { process: 'second', running: true }, { process: 'first' , running: true }, { process: 'second', running: false }, { process: 'first' , running: false }],
result = Object.fromEntries(Object
.entries(data.reduce((r, { process, running }) => {
r[process] ??= 0;
r[process] += running || -1;
return r;
}, {}))
.map(([k, v]) => [k, !!v])
);
console.log(result);
Upvotes: 2