cup_of
cup_of

Reputation: 6687

Search nested array of objects and return the full path to the object

Say I have the following object:

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: []
  }
]

I'd like to perform a function on this nested object that will return the 'path' to the object I'm searching for.

So something like

getPath(pages, '1.2.1')

will return:

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

Here's what I have so far. Its just a recursive function to find the object I want. I'm stuck on how to build the path as I'm traversing through the object though.

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 possibleResult;
    }
  }
}

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

Upvotes: 2

Views: 848

Answers (1)

Ele
Ele

Reputation: 33726

You can use this alternative for getting the path, it's a recursive approach and uses an array called path as param in order to track the visited levels.

Assuming the ID's are uniques regardless of the location/level.

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; }

Upvotes: 2

Related Questions