Find the value inside the array of objects that include children from the array of objects

Viewed 2648

I have array of objects that include children from the array of objects and i need to find value inside parent array or find value inside childrens of this array etc. Maybe recursive. I trided like this:

var array = [
  {
    id: 1,
    value: 'value',
    children: null
  },
  {
    id: 2,
    value: 'my value',
    children: [
      {
        id: 'child1',
        value: 'my value',
        children: null
      },
      {
        id: 'child2',
        value: 'value',
        children: null
      },
      {
        id: 'child3',
        value: 'value,
        children: [
          {
            id: 'childchild1',
            value: 'my value',
            children: null
          }
        ]
      }
    ]
  },
  {
    id: 3,
    value: 'value',
    children: null
  },
  {
    id: 4,
    value: 'my value',
    children: null
  }
]


function find(searchData, target){
  return target.filter((f)=>{
    if(f.value.includes(searchData)){
      return true
    }
    if(f.children){
      return find(searchData, f.children)
    }
  })
}

find('my', array)

It's returns source array but i need array which includes text 'my'

3 Answers

Because you have a nested structure, you can't use .filter to get all nested objects - .filter will only return to you the matching objects on the topmost level. Instead, define an empty array on the initial call, then push to that array when an item passes the test, and pass the array around to each recursive call. Finally, return that array:

var array=[{id:1,value:'value',children:null},{id:2,value:'my value',children:[{id:'child1',value:'my value',children:null},{id:'child2',value:'value',children:null},{id:'child3',value:'value',children:[{id:'childchild1',value:'my value',children:null}]}]},{id:3,value:'value',children:null},{id:4,value:'my value'}];

function find(searchData, target, accum=[]){
  target.forEach((f)=>{
    if(f.children){
      find(searchData, f.children, accum)
    }
    if(f.value.includes(searchData)){
      accum.push(f);
    }
  });
  return accum;
}

console.log(find('my', array));

(result is probably seen more easily via browser console than via stack snippet console)

Here is a functional programming style implementation. For simplifying the output I just collected the id values of the matches. If you want the whole object, then replace obj.id by obj:

const array = [{id: 1,value: 'value',children: null},{id: 2,value: 'my value',children: [{id: 'child1',value: 'my value',children: null},{id: 'child2',value: 'value',children: null},{id: 'child3',value: 'value' ,children: [{id: 'childchild1',value: 'my value',children: null}]}]},{id: 3,value: 'value',children: null},{id: 4,value: 'my value'}];

const find = (searchData, target) => (target || []).reduce(
        (acc, obj) => acc.concat(obj.value.includes(searchData) ? obj.id : [],
                                 find(searchData, obj.children)),
        []
    );

const result = find('my', array);
console.log(result);

Just a bit too late, here is another recursive find:

var array = [
  {
    id: 1,
    value: 'value',
    children: null,
  },
  {
    id: 2,
    value: 'my value',
    children: [
      {
        id: 'child1',
        value: 'my value',
        children: null,
      },
      {
        id: 'child2',
        value: 'value',
        children: null,
      },
      {
        id: 'child3',
        value: 'value',
        children: [
          {
            id: 'childchild1',
            value: 'my value',
            children: null,
          },
        ],
      },
    ],
  },
  {
    id: 3,
    value: 'value',
    children: null,
  },
  {
    id: 4,
    value: 'my value',
  },
];

function find(search, arr) {
  function recur(result, search, arr) {
    if (!(arr && arr.length)) {
      return result;
    }
    return result
      .concat(
        ...arr.filter((item) =>
          item.value.includes(search),
        ),
      )
      .concat(
        ...arr.map((item) =>
          recur([], search, item.children),
        ),
      );
  }
  return recur([], search, arr);
}
console.log(find('my', array));

Related