5

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 ?

0

5 Answers 5

4

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);

Sign up to request clarification or add additional context in comments.

Comments

1

Use Array.prototype.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 result = allModules.reduce((modulesObj, moduleName) => {
  modulesObj[moduleName] = [{ user: [] }]
  
  for (let user in receiver) {
    if (receiver[user].module.includes(moduleName)) {
      modulesObj[moduleName][0].user.push(user)
    }
  }
  
  return modulesObj
}, {})


console.log(result)

Comments

0

Try this one

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

const userByModules = Object.keys(receiver).reduce(function (acc, user) {
	receiver[user].module.forEach((module) => {
		if (acc[module]) {
          acc[module].user.push(user);
        } else {
          acc[module] = {user: [user]};
        }
	});
    return acc;
}, {});

console.log(userByModules);

Comments

0
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"];

let reduce = () => {
  // create output object
  let output = {};

  // add modules into output
  allModules.map(mod => {
    return (output[mod] = [{ 'user': []}]);
  });

  // map users to modules
  for (let userKey in receiver) {
    let userModules = receiver[userKey].module;
    userModules.forEach(mod => {
      if(output.hasOwnProperty(mod)) {
        output[mod][0]['user'].push(userKey);
      }
    });
  }
};

reduce();

Straightforward way of getting the job done. No fancy functions used.Hopefully this logic would be easy to follow.

Comments

0

The below snippet reduce the provided allModules array into the expected result. However, I think this structure

"a_normal": {
      "user": [
        "USER1",
        "USER2"
      ]
 },
...

make sense more than the below snippet because you have to access the first index of each module to get user value

"a_normal": [
    {
      "user": [
        "USER1",
        "USER2"
      ]
    }
  ],

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 result = allModules.reduce((prevResult, curModule, index) => {
  if(!prevResult[curModule]) {
    prevResult[curModule]=[{user:[]}];
  }

  Object.keys(receiver).forEach((user) => {
    if(receiver[user].module.includes(curModule) &&
      !prevResult[curModule][0].user.includes(user)) {
        prevResult[curModule][0].user.push(user);
    }
  });

  return prevResult;
},{});
console.log(JSON.stringify(result, null, 2));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.