Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript - reduce the given object into one data structure

Tags:

javascript

I need to reduce the given object into some datastructure. This is my input object.

const receiver =  {
      USER1: {
        module: ['a_critical', 'a_normal','b_normal']
      },
      USER2: {
        module: ['a_critical', 'a_normal','b_critical']
      }, 
      USER3: {
        module: ['a_critical']
      }
    };

const allModules = ['a_normal', 'a_critical', 'b_normal', 'b_critical']; 

Desired output:

{
  "a_critical": [
    {
      "user": [
        "USER1", "USER2", "USER3"
      ]
    }
  ],
  "a_normal": [
    {
      "user": [
        "USER1", "USER2"
      ]
    }
 ],
  "b_normal": [
    {
      "user": [
        "USER1"
      ]
    }
  ],
  "b_critical": [
    {
      "user": [
        "USER2"
      ]
    }
  ]
} 

I have tried doing but i was getting some problems. I am getting some duplicate properties which should be there. I can share the code on what i have tried.

const receiverObj = {};

let count = 0;
Object.keys(receiver).forEach((item) => {
    receiver[item].module.forEach((module) => {
      if(allModules.includes(module)) {
        count  = 1;
        if(count) {
        receiverObj[module] = [];
           receiverObj[module].push({user: [item] });
        }
        receiverObj[module].push({user: item });
        count = 0;
      }
    })
});

console.log(JSON.stringify(receiverObj, null, 2)); 

Actual result which i got:

{
  "a_critical": [
    {
      "user": [
        "USER3"
      ]
    },
    {
      "user": "USER3"
    }
  ],
  "a_normal": [
    {
      "user": [
        "USER2"
      ]
    },
    {
      "user": "USER2"
    }
  ],
  "b_normal": [
    {
      "user": [
        "USER1"
      ]
    },
    {
      "user": "USER1"
    }
  ],
  "b_critical": [
    {
      "user": [
        "USER2"
      ]
    },
    {
      "user": "USER2"
    }
  ]
} 

Is there any optimal way of doing this ? can someone help ?

like image 536
unnamed-bull Avatar asked Aug 07 '19 04:08

unnamed-bull


People also ask

Can we use reduce on objects in JavaScript?

The array reduce in JavaScript is a predefined method used to reduce an array to a single value by passing a callback function on each element of the array. It accepts a function executed on all the items of the specified array in the left-to-right sequence. The returned single value is stored in the accumulator.

Can I use reduce on object?

But did you know you can reduce them to objects as well? First, a quick overview of how reduce works. The reduce method receives two arguments: a function and an initial value. The function will run run for every value in the array, and receives two arguments as well: the accumulator, or acc , and the current value .

What is reduce () in JavaScript?

The reduce() method executes a user-supplied "reducer" callback function on each element of the array, in order, passing in the return value from the calculation on the preceding element. The final result of running the reducer across all elements of the array is a single value.

How do you use reduce on array of objects in JavaScript?

The reduce() method executes the function for each value of the array (non-empty array) from left to right. The reduce() method has the following syntax: let arr = [];arr. reduce(callback(acc, curVal, index, src), initVal);


1 Answers

Iterate over each module in a reduce callback, creating a { user: [] } object in the accumulator if it doesn't exist yet, and then push to that array:

const receiver =  {
      USER1: {
        module: ['a_critical', 'a_normal','b_normal']
      },
      USER2: {
        module: ['a_critical', 'a_normal','b_critical']
      }, 
      USER3: {
        module: ['a_critical']
      }
    };

const output = Object.entries(receiver)
  .reduce((a, [user, { module }]) => {
    module.forEach((name) => {
      if (!a[name]) {
        a[name] = { user: [] };
      }
      a[name].user.push(user);
    });
    return a;
  }, {});
console.log(output);

You could also create the accumulator object in advance, if you wanted, since you have allModules, thereby avoiding conditionals inside the .reduce:

const receiver =  {
      USER1: {
        module: ['a_critical', 'a_normal','b_normal']
      },
      USER2: {
        module: ['a_critical', 'a_normal','b_critical']
      }, 
      USER3: {
        module: ['a_critical']
      }
    };

const allModules = ['a_normal', 'a_critical', 'b_normal', 'b_critical']; 
const accum = Object.fromEntries(
  allModules.map(
    name => [name, { user: [] }]
  )
);

const output = Object.entries(receiver)
  .reduce((a, [user, { module }]) => {
    module.forEach((name) => {
      a[name].user.push(user);
    });
    return a;
  }, accum);
console.log(output);
like image 160
CertainPerformance Avatar answered Nov 15 '22 05:11

CertainPerformance