Как заполнить плоский массив в javascript - PullRequest
0 голосов
/ 05 августа 2020

Моя цель - создать древовидную структуру, которая автоматически упорядочивает следующие данные. Свойство subSkills содержит список ссылок на идентификаторы других навыков.

[
  {
    name: "chess";
    subSkills: [];
    parentId: "games";
    _id: "chess";
  },
  {
    name: "games";
    subSkills: ["chess",...];
    parentId: "";
    _id: "games";
  },
]
export default interface ISkill {
  name: string;
  subSkills: string[] | ISkill[];
  parentId: string;
  _id: string;
}

Результат должен быть примерно таким.

[
 {
  name: "games";
  subSkills: [
    {
      name: "chess";
      subSkills: [{}...];
      parentId: "games";
      _id: "chess";
    }
  ];
  parentId: "";
  _id: "games";
 }, ... {}
]

Я должен отметить, что функция должна уметь обрабатывать любой уровень глубины. Поскольку у меня нет опыта работы с подобными вещами, я был бы признателен, если бы кто-нибудь мог описать свой образ мышления.

Заранее спасибо.

РЕДАКТИРОВАТЬ: У меня есть несколько деревьев / корней в базе данных . Таким образом, несколько навыков имеют родительский идентификатор "".

1 Ответ

1 голос
/ 05 августа 2020

Насколько я понимаю, каждый объект данного массива будет либо root, либо дочерним по отношению к другому root объекту. Я не знаю, ошибочно ли вы заполнили массив subSkills объекта или это следует учитывать, поэтому его следует заменить на весь объект, если он найден? согласно моему предположению, у меня просто нет subSkills в виде строк, я установил все subSkills на пустой массив для начала, дайте мне знать, следует ли это учитывать, пожалуйста. в противном случае вы можете просто увидеть, соответствует ли строка, тогда вы можете удалить ее из массива и заменить ее самим дочерним объектом.

Вот мое решение:

const givenArray = [
  {
    name: "chess",
    subSkills: [],
    parentId: "games",
    _id: "chess",
  },
  {
    name: "games",
    subSkills: [],
    parentId: "",
    _id: "games",
  },
  {
    name: "programming dev",
    subSkills: [],
    parentId: "chess",
    _id: "programming",
  },
  {
    name: "basketball 01",
    subSkills: [],
    parentId: "chess",
    _id: "basketball",
  },
];
const skillsAggregator = (skills) => {
  const newSkills = [...skills];

  newSkills.forEach((skill) => {
    if (!!skill.parentId.length) {
      addSubSkills(newSkills, skill);
    }
  });

  return newSkills;
};
const addSubSkills = (skills, currentSkill) => {
  for (let i = 0; i < skills.length; i++) {
    const skill = skills[i];

    if (currentSkill.parentId === skill._id) {
      skill.subSkills.push(currentSkill);
      break;
    }
  }
};

console.log(JSON.stringify(skillsAggregator(givenArray), null, 2));

ПРИМЕЧАНИЕ Если вы можете обновить структуру данных (а вы можете) до Map или литерального объекта, алгоритм будет быстрее, чем с массивом, вот пример с дополнительным уровнем вложенности:

const givenArray = {
  chess: {
    name: "chess",
    subSkills: [],
    parentId: "games",
    _id: "chess",
  },
  games: {
    name: "games",
    subSkills: [],
    parentId: "",
    _id: "games",
  },
  programming: {
    name: "programming dev",
    subSkills: [],
    parentId: "chess",
    _id: "programming",
  },
  basketball: {
    name: "basketball 01",
    subSkills: [],
    parentId: "chess",
    _id: "basketball",
  },
  football: {
    name: "football",
    subSkills: [],
    parentId: "basketball",
    _id: "football",
  },
};
const skillsAggregator = (skills) => {
  const newSkills = { ...skills };

  Object.entries(newSkills).forEach(([id, skill]) => {
    if (!!skill.parentId.length) {
      newSkills[skill.parentId].subSkills.push(skill);
    }
  });

  return newSkills;
};

console.log(JSON.stringify(skillsAggregator(givenArray), null, 2));
...