Рекурсивный перебор массива объектов

211
03 мая 2022, 02:50

Дан массив объектов:

let arr = [
  {
    id: 1000,
    name: "Like",
    parent_id: 1003,
    parent_name: "Root"
  },
  {
    id: 1001,
    name: "Count",
    parent_id: 1000,
    parent_name: "Like"
  },
  {
    id: 1002,
    name: "Subscribe",
    parent_id: "",
    parent_name: ""
  },
  {
    id: 1003,
    name: "Root",
    parent_id: "",
    parent_name: ""
  }
];

Задача - преобразовать его в следующий вид:

track = {
    1000: '/ > Root>Like',
    1001: '/ > Root>Like > Count',
    1002: '/ > Subscribe',
    1003: '/ > Root'
}

Суть функции - преобразовать массив в объект, в котором ключами будут значения id из объектов массива, а значениями этих ключей будут пути, формирующиеся по принципу: если в ключе parent_id пустая строка - возвращается имя данного объекта, это, стало быть базовый случай в рекурсивной функции, но если в parent_id есть значение, то возвращается значение name и происходит поиск объекта у которого значение id равно значению parent_id данного объекта и возвращается его name тоже и т.д.

Базовый случай понятно как прописать:

for(let i in arr) {
    if(arr[i].parent_id == "") {
        ans[arr[i].id] = '/ ' + arr[i].name
    }
  }

Но вот рекурсивно "пробегать" все объекты не получается реализовать.

Answer 1

let arr = [
  {
    id: 1000,
    name: "Like",
    parent_id: 1003,
    parent_name: "Root"
  },
  {
    id: 1001,
    name: "Count",
    parent_id: 1000,
    parent_name: "Like"
  },
  {
    id: 1002,
    name: "Subscribe",
    parent_id: "",
    parent_name: ""
  },
  {
    id: 1003,
    name: "Root",
    parent_id: "",
    parent_name: ""
  }
];
//метод для рекурсивного обхода массива
function recursion(parent_id, arResult = []) {
  for (let item of arr) {
    //если переданный parent_id равен id в массиве
    if (item.id === parent_id) {
      //добавляем имя родителя в начало массива
      arResult.unshift(item.name);
      //если в этой итерации есть parent, то идём получаеть его имя
      if (!!item.parent_id) {
        recursion(item.parent_id, arResult);
      }
      continue;
    }
  }
  //массив превращаем в строку с делителем '>'
  return `${arResult.join(">")} > `;
}
let objResult = {}, parentName = "";
for (let item of arr) {
   //parentName всегда пустой на новой итерации
  parentName = '';
  //если parent_id заполнен
  if (!!item.parent_id) {
    //если у элемента в итерации есть parent, то идём получаеть его имя
    parentName = recursion(item.parent_id, []);
  }
  //собираем результат
  objResult[item.id] = `/ > ${parentName}${item.name}`;
}
console.log(objResult);

Answer 2

получилось так

const abra = (arr) => {
  let ans = {}
  const way = '>'
  let el
  const catabra = (inner) => {
    if(typeof inner === 'object'){
      el = arr.find(el => inner.parent_id === el.id)
      return el?.parent_name ? 
      '/' + catabra(el.parent_name) + catabra(inner.parent_name) + catabra(inner.name) :
            inner.parent_name ? 
      '/' + catabra(inner.parent_name) + catabra(inner.name) :
      '/' +  catabra(inner.name)
    }
    return way + inner
  }
  arr.forEach((elem) => {
      ans[elem.id] = catabra(elem)  
  })
  return ans

}

READ ALSO
Не работает spinner

Не работает spinner

не работает spinnerВыдаёт такую ошибку:

311
Как рассчитать координаты второй точки на карте?

Как рассчитать координаты второй точки на карте?

У меня есть координаты первой точки на карте, есть расстояние между точками и есть градусы поворота относительно сторон света (с компаса)Подскажите...

174