Abhishek
Abhishek

Reputation: 174

Check key in deep nested object in array

I have array of nested object. I have to check the property of key object and return its value. I have done it using the for loop and checking with children property exist or not. But I think it is not optimal way to do it. what will be most optimal way to do it. Here is the code array of object data. I have to get text for the id 121.

var abc = [
  {
    id: 1,
    text: 'One',
    children: [
      {id: 11, text: 'One One'},
      {id: 12, text: 'One two', 
       children: [ {id: 121, text: 'one two one'} ]}
    ]
  },
  {
    id: 2,
    text: 'two'
  }
];

My approach is very specific to this problem. Here it is

for(var val of abc){

  if(val.id == 121){
    console.log('in first loop',val.text);
    break;
  }

  if(Array.isArray(val.children)){

   for(var childVal of val.children) {
       if(childVal.id == 121){
        console.log('in first child', childVal.text); 
         break;
       }
     if(Array.isArray(childVal.children)){
       for(var nextChild of childVal.children){
         if(nextChild.id == 121){
           console.log('in next child', nextChild.text); 
           break;
         }

       }

       }
   }

  }

}

Upvotes: 1

Views: 106

Answers (3)

Roko C. Buljan
Roko C. Buljan

Reputation: 206344

Given your Nodes have nested Nodes in a children property, using a recursion and Array.prototype.find() to find a Node by ID:

const getNode = (a, id, c = 'children', r) => {
  const rec = a => a.find(o => o.id==id && (r=o) || c in o && rec(o[c]));
  return rec(a) && r;
};


const abc = [{id: 1, text: 'One', children: [{id: 11, text: 'One one'}, {id: 12, text: 'One two', children: [{id: 121, text: 'One two one'}]}]}, {id: 2, text: 'Two' }];
console.log( getNode(abc, 121)?.text ); // One two one

Upvotes: 0

Nina Scholz
Nina Scholz

Reputation: 386680

You could take an approach with a short circuit and return a result from a wanted property.

const
    getValue = (object, key, id) => {
        const search = o => {
            if (!o || typeof o !== 'object') return;
            if (o.id === id) return { value: o[key] };
            var value;
            Object.values(o).some(p => value = search(p));
            return value;
        };
        return search(object)?.value;
    };

var array = [{ id: 1, text: 'One', children: [{ id: 11, text: 'One One' }, { id: 12, text: 'One two', children: [{ id: 121, text: 'one two one' }] }] }, { id: 2, text: 'two' }];

console.log(getValue(array, 'text', 121));
console.log(getValue(array, 'text', 3000));

Upvotes: 1

Nenad Vracar
Nenad Vracar

Reputation: 122077

You could create recursive function using for...in loop that returns the matched object and then you can get its text property.

var abc = [{"id":1,"text":"One","children":[{"id":11,"text":"One One"},{"id":12,"text":"One two","children":[{"id":121,"text":"one two one"}]}]},{"id":2,"text":"two"}]

function getProp(data, key, value) {
  let result = null;


  for (let i in data) {
    if (typeof data[i] == 'object' && !result) {
      result = getProp(data[i], key, value)
    }

    if (i == key && data[i] == value) {
      result = data
    }
  }

  return result;
}

const result = getProp(abc, 'id', 121)
console.log(result)

Upvotes: 2

Related Questions