Поиск по вложенному массиву объектов и возврат полного пути к объекту

#javascript

#javascript

Вопрос:

Допустим, у меня есть следующий объект:

 const pages = [
  {
    name: 'a',
    id: '1',
    pages: [
      {
        name: 'b',
        id: '1.1',
        pages: []
      },
      {
        name: 'c',
        id: '1.2',
        pages: [
          {
            name: 'd',
            id: '1.2.1',
            pages: []
          }
        ]
      },
    ]
  },
  {
    name: 'e',
    id: '2',
    pages: []
  }
]
  

Я хотел бы выполнить функцию для этого вложенного объекта, которая вернет «путь» к объекту, который я ищу.

Итак, что-то вроде

getPath(pages, '1.2.1')

вернет:

 [
  {
    name: 'a',
    id: '1'
  },
  {
    name: 'c',
    id: '1.2'
  },
  {
    name: 'd'
    id: '1.2.1'
  }
]
  

Вот что у меня есть на данный момент. Это просто рекурсивная функция для поиска нужного мне объекта. Я застрял на том, как построить путь, когда я прохожу через объект.

 const pages = [
  {
    name: 'a',
    id: '1',
    pages: [
      {
        name: 'b',
        id: '1.1',
        pages: []
      },
      {
        name: 'c',
        id: '1.2',
        pages: [
          {
            name: 'd',
            id: '1.2.1',
            pages: []
          }
        ]
      },
    ]
  },
  {
    name: 'e',
    id: '2',
    pages: []
  }
]


function getPath(pages, pageId) {
  let path = [];

  for (let i = 0; i < pages.length; i  ) {
    const item = search(pages[i], pageId);
    
    // build path here?
  
    if (item) {
      return item;
    }
  }
}

function search(obj, id) {
  if (obj.id === id) {
    return obj;
  }

  for (let i = 0; i < obj.pages.length; i  ) {
    const possibleResult = search(obj.pages[i], id);
    if (possibleResult) {
      return possibleResu<
    }
  }
}

console.log(getPath(pages, '1.2.1'))  

Ответ №1:

Вы можете использовать эту альтернативу для получения пути, это рекурсивный подход и использует массив, называемый path как param, для отслеживания посещенных уровней.

Предполагая, что идентификаторы являются уникальными независимо от местоположения / уровня.

 const pages = [  {    name: 'a',    id: '1',    pages: [      {        name: 'b',        id: '1.1',        pages: []      },      {        name: 'c',        id: '1.2',        pages: [          {            name: 'd',            id: '1.2.1',            pages: []          }        ]      },    ]  },  {    name: 'e',    id: '2',    pages: []  }];
const loop = (arr, target, index, path) => {
  if (arr[index].id === target) {
    path.push({name: arr[index].name, id: arr[index].id});
  } else if (arr[index].pages.length) {
    path.push({name: arr[index].name, id: arr[index].id});    
    arr[index].pages.forEach((_, i, a) => {
      loop(a, target, i, path);      
    });
    
    if (path[path.length - 1].id === arr[index].id) path.pop();
  }
};

let getPath = (arr, target) => {
  let path = [];
  arr.forEach((_, i, a) => loop(a, target, i, path));
  return path;
};

console.log(getPath(pages, '1.2.1'));  
 .as-console-wrapper { max-height: 100% !important; top: 0; }  

Комментарии:

1. спасибо за ответ! но, к сожалению, похоже, что это работает только для первого индекса массива страниц. например, сделайте это вместо getPath(pages, '2', 0, path);