Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Search nested array of objects and return full parents as results in JavaScript

Tags:

javascript

I've successfully written a recursive function to loop through a nested object and find the results. But I'm having a hard time adding the entire parent if its children pass the test. I have the following code:

const myObj = [
  {
    name: '1',
    pages: [
      {
        name: '1.1',
        pages: []
      },
      {
        name: '1.2',
        pages: []
      },
    ]
  },
  {
    name: '2',
    pages: []
  },
  {
    name: '3',
    pages: []
  }
]

function searchPages(searchQuery, obj) {
  let searchResults = [];
  for (let i = 0; i < obj.length; i++) {
    let item = searchString(obj[i], searchQuery);

    if (item) {
      searchResults.push(item);
    }
  }
  return searchResults;
}

function searchString(obj, string) {
  if (obj.name.includes(string)) {
    return obj;
  }

  for (let i = 0; i < obj.pages.length; i++) {
    const possibleResult = searchString(obj.pages[i], string);
    if (possibleResult) {
      return possibleResult;
    }
  }
}

let searchResults = searchPages('1.1', myObj);
console.log(searchResults);

This searches the nested array properly and gives the correct result:

  {
    "name": "1.1",
    "pages": []
  }

But I would like to return the entire parent object, instead of just the child object. So the expected result is this:

  {
    name: '1',
    pages: [
      {
        name: '1.1',
        pages: []
      },
      {
        name: '1.2',
        pages: []
      },
    ]
  }

How can I modify my function to achieve this?

Keep in mind this is just a small object just for readability purposes. My actual object will have many more levels and properties.

like image 303
cup_of Avatar asked Jan 26 '23 11:01

cup_of


1 Answers

You could take a recursive approach and check if the nested arrays have the wanted name.

function searchPages(array, string) {
    const find = ({ name, pages }) => name.includes(string) || pages && pages.some(find);
    return array.filter(find);
}

const
    data = [{ name: '1', pages: [{ name: '1.1', pages: [] }, { name: '1.2', pages: [] }] }, { name: '2', pages: [] }, { name: '3', pages: [] }],
    searchResults = searchPages(data, '1.1');

console.log(searchResults);
.as-console-wrapper { max-height: 100% !important; top: 0; }
like image 141
Nina Scholz Avatar answered Jan 29 '23 12:01

Nina Scholz