Reputation: 965
Working with the following object, how can the roles
=> name
be added to the sites
=> userPermission
object with the matching roleId
?
For example, the userPermission
key of the first sites
entry would be updated to:
"userPermission": {
"roleId": 6,
"roleName": "Field Representative"
}
Once the roleName
key has been mapped, there is no longer a need for the roles
array and it can be removed from the end result as shown in the expected outcome.
const obj = {
"id": 542,
"createdAt": "2018-12-06T22:34:12.553Z",
"sites": [
{
"id": 10,
"siteId": "sixtysixone",
"edition": "pro",
"userPermission": {
"roleId": 6
}
},
{
"id": 2,
"siteId": "amplify",
"edition": "pro",
"userPermission": {
"roleId": 4
}
}
],
"roles": [
{
"id": 6,
"name": "Field Representative"
},
{
"id": 4,
"name": "Program Manager"
}
]
};
Expected outcome:
const outcome = {
"id": 542,
"createdAt": "2018-12-06T22:34:12.553Z",
"sites": [
{
"id": 10,
"siteId": "sixtysixone",
"edition": "pro",
"userPermission": {
"roleId": 6,
"roleName": "Field Representative"
}
},
{
"id": 2,
"siteId": "amplify",
"edition": "pro",
"userPermission": {
"roleId": 4
"roleName": "Program Manager"
}
}
]
};
I have attempted with a combination of .map
and .find
, but feel there is a much more simple/readable way to accomplish this.
const outcome = obj.map(o => ({
...o,
sites: o.sites
.map(s => ({
...s,
roleName: o.roles
.find(r => r.id === s.roleId).name,
})),
}));
Upvotes: 2
Views: 1366
Reputation: 31712
You could first turn the roles
array into an object to ease the retrieval of the role names:
let rolesMap = obj.roles.reduce((acc, role) =>
(acc[role.id] = role.name, acc),
Object.create(null)
);
Then just loop over the sites array, adding the roleName
property to each site userPermission
object by fetching the value from rolesMap
:
obj.sites.forEach(site => {
if(rolesMap[site.userPermission.roleId]) {
site.userPermission.roleName = rolesMap[site.userPermission.roleId];
}
});
You can skip the if
test if you know for sure that each site object will have an associated role object in the roles
array. And if you want to create a new sites
object then use map
instead of forEach
.
And finally you can delete
the roles
property if you want:
delete obj.roles;
Example:
const obj = {"id":542,"createdAt":"2018-12-06T22:34:12.553Z","sites":[{"id":10,"siteId":"sixtysixone","edition":"pro","userPermission":{"roleId":6}},{"id":2,"siteId":"amplify","edition":"pro","userPermission":{"roleId":4}}],"roles":[{"id":6,"name":"Field Representative"},{"id":4,"name":"Program Manager"}]};
let rolesMap = obj.roles.reduce((acc, role) =>
(acc[role.id] = role.name, acc),
Object.create(null)
);
obj.sites.forEach(site => {
if(rolesMap[site.userPermission.roleId]) {
site.userPermission.roleName = rolesMap[site.userPermission.roleId];
}
});
delete obj.roles;
console.log(obj);
Upvotes: 1
Reputation: 138537
Create a map of roles:
const roles = new Map(obj.roles.map(({ id, name }) => [id, { roleId: id, roleName: name }]));
Then you can just look up:
const outcome = {
...obj,
sites: obj.sites.map(site => ({
...site,
userPermission: roles.get(site.userPermission.roleId),
}),
roles: undefined,
};
Upvotes: 3
Reputation: 35263
You could loop over the sites
and update the userPermission
using find
(This assumes that every roleId
exists in roles
. Otherwise, you need to check if find
returns undefined
first)
const obj = {"id":542,"createdAt":"2018-12-06T22:34:12.553Z","sites":[{"id":10,"siteId":"sixtysixone","edition":"pro","userPermission":{"roleId":6}},{"id":2,"siteId":"amplify","edition":"pro","userPermission":{"roleId":4}}],"roles":[{"id":6,"name":"Field Representative"},{"id":4,"name":"Program Manager"}]};
obj.sites.forEach(site => {
site.userPermission.roleName =
obj.roles.find(r => r.id === site.userPermission.roleId).name
})
delete obj.roles;
console.log(obj)
Upvotes: 1