Reputation: 361
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 ?
Upvotes: 5
Views: 81
Reputation: 8152
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)
Upvotes: 1
Reputation: 1618
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));
Upvotes: 0
Reputation: 545
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.
Upvotes: 0
Reputation: 1063
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);
Upvotes: 0
Reputation: 371069
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);
Upvotes: 4