将嵌套的对象键映射到另一个键

时间:2019-02-22 15:44:04

标签: javascript arrays javascript-objects

使用以下对象,如何将roles => name添加到具有匹配sites的{​​{1}} => userPermission对象中?

例如,第一个roleId条目的userPermission键将更新为:

sites

一旦映射了 "userPermission": { "roleId": 6, "roleName": "Field Representative" } 键,就不再需要roleName数组,可以将其从最终结果中删除,如预期结果所示。

roles

预期结果:

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

我曾尝试使用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" } } ] }; .map的组合,但是感觉有一种更简单/可读的方法来完成此操作。

.find

3 个答案:

答案 0 :(得分:3)

创建角色图:

 const roles = new Map(obj.roles.map(({ id, name }) => [id, { roleId: id, roleName: name }]));

然后您可以向上看:

const outcome = {
  ...obj,
  sites: obj.sites.map(site => ({ 
    ...site,
    userPermission: roles.get(site.userPermission.roleId),
  }),
  roles: undefined,
};

答案 1 :(得分:1)

您可以遍历<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script> <canvas id="c" width="400" height="400"></canvas>并使用find更新sites

(这假设userPermission中存在每个roleId。否则,您需要检查roles是否首先返回find

undefined

答案 2 :(得分:0)

您可以首先将roles数组变成一个对象以简化角色名称的检索:

let rolesMap = obj.roles.reduce((acc, role) =>
    (acc[role.id] = role.name, acc),
    Object.create(null)
);

然后循环遍历sites数组,通过从roleName获取值将userPermission属性添加到每个站点rolesMap对象:

obj.sites.forEach(site => {
    if(rolesMap[site.userPermission.roleId]) {
        site.userPermission.roleName = rolesMap[site.userPermission.roleId];
    }
});

如果您确定每个站点对象在if数组中都有一个关联的角色对象,则可以跳过roles测试。而且,如果您想创建一个新的sites对象,请使用map而不是forEach

最后,您可以根据需要delete roles属性:

delete obj.roles;

示例:

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