JPS
JPS

Reputation: 2760

Reduce object array into single object

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

Answers (2)

iwaduarte
iwaduarte

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

Nina Scholz
Nina Scholz

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

Related Questions