#javascript #for-loop #data-structures
#язык JavaScript #для-петли #структуры данных
Вопрос:
Я работал над вопросом о формировании данных и, наконец, получил ответ.
Однако в моем ответе слишком много циклов, и это замедлит временную сложность при реализации.
Ниже приведен мой код:
const userInfo = []; for (let i = 0; i lt; projects.length; i ) { const userProject = projects[i].userProjects; for (let j = 0; j lt; userProject.length; j ) { const userExist = userInfo.some((item) =gt; item.userId.includes(userProject[j].user.userId) ); if (!userExist) userInfo.push(userProject[j].user); } } userInfo.forEach((user) =gt; { let tempArr = []; for (let i = 0; i lt; projects.length; i ) { const userProject = projects[i].userProjects; for (let j = 0; j lt; userProject.length; j ) { if (user.userId === userProject[j].userId) tempArr.push({ projectId: projects[i].projectId, name: projects[i].name, }); } } user.project = tempArr; }); console.log(userInfo);
Есть ли способ оптимизировать свой код? Я попытался объединить вложенные циклы for вместе, но это не сработало…
Пожалуйста, помогите. Большое вам спасибо!!!
Комментарии:
1. Что вам нужно, так это лучшая структура данных, организованная в соответствии с тем, что должно делать ваше приложение.
2. Поделитесь своими данными и, пожалуйста, расскажите, каков ожидаемый результат
Ответ №1:
В верхней части два внешних цикла выглядят необходимыми (поскольку у вас есть N проектов * M пользовательских проектов), но третий .some
— нет-измените userInfo
массив на отображение идентификаторов пользователей для их пользователей, поэтому во втором цикле вам нужно только посмотреть, существует ли идентификатор пользователя ( O(1)
), и назначить, если это не так.
Вместо назначения пользователя назначьте объект нужной вам формы в конце — a [{ projectId, name }]
. Это избавит вас от необходимости снова просматривать весь массив — как только вы проверите , нужно ли вам создавать окружающий массив для userId
, вы можете переместить объект в массив независимо от того, приходилось ли вам создавать массив на этой итерации или нет.
const userProjectsByUserId = new Map(); for (const { userProjects, projectId, name } of projects) { for (const { user } of projects) { if (!userProjectsByUserId.has(user.userId)) { userProjectsByUserId.set(user.userId, { user, projects: [] }]); } userProjectsByUserId.get(user.userId).projects.push({ projectId, name }); } }
Это даст вам карту формы
userId =gt; { user, projects: [ { projectId, name }, ...
Если вам нужна точная структура данных, которую дает вам ваш текущий код, затем выполните:
const output = [...userProjectsByUserId.values()] .map(({ user, projects }) =gt; ({ ...user, project: projects }));
(хотя вы могли бы рассмотреть возможность использования projects
вместо project
, так как это коллекция проектов, а не один проект)
Комментарии:
1. Огромное спасибо. Что делать, если не использовать новую карту структуры данных (), а вместо этого использовать массив?
2. Если вы используете массив, вы не сможете сразу найти в нем идентификатор пользователя — вместо этого вам придется искать в массиве совпадение (
O(n)
) вместо того, чтобы просто искать его как свойство карты или объекта (O(1)
). Поэтому не используйте массив при группировке; это сделает вещи слишком неэффективными.3. Понял, большое вам спасибо за вашу помощь!!