Сопоставление ключа вложенного объекта с другим ключом

Работая со следующим объектом, как можно добавить roles => name к объекту sites => 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, но чувствую, что есть гораздо более простой/удобочитаемый способ сделать это.

const outcome = obj.map(o => ({
  ...o,
  sites: o.sites
    .map(s => ({
      ...s,
      roleName: o.roles
        .find(r => r.id === s.roleId).name,
   })),
}));

Что вы пробовали до сих пор, чтобы решить вашу проблему?

Alberti Buonarroti 22.02.2019 16:46

Я не думаю, что вы можете map объект.

bird 22.02.2019 17:16
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
2
685
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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,
};

Вы можете перебрать sites и обновить userPermission, используя find

(Это предполагает, что каждый roleId существует в roles. В противном случае вам нужно сначала проверить, возвращает ли findundefined)

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.info(obj)

Вы можете сначала превратить массив roles в объект, чтобы упростить поиск имен ролей:

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

Затем просто переберите массив сайтов, добавив свойство 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.info(obj);

Другие вопросы по теме