Skip to content Skip to sidebar Skip to footer

Recursively Find Keys On An Object

I have a javascript object structured like this; brand: { group: { subGroup: { items: [] }, otherSub: { items: [] } } } Given an array of keys ['

Solution 1:

Here's a pretty sketchy way that works.

const find = (keys, obj) => {
  const string = JSON.stringify(obj);
  return keys.reduce(({ present, missing }, key) => {
    const match = string.match(new RegExp(`"${key}":`));
    if (match) {
      present.push(key);
    } else {
      missing.push(key);
    }
    return { present, missing };
  }, { present: [], missing: [] });
}

Solution 2:

You can use this function made for you ;)

var getAttrs = function(obj) {
  return [].concat.apply([], Object.keys(obj).map(function (key) { 
    var results = [key]
    if (typeof obj[key] === 'object') {
      Array.prototype.push.apply(results, getAttrs(obj[key]))
    }
    return results
  }))
}

It return the list of properties and children properties.

getAttrs({brand: {
  group: {
    subGroup: {
       items: []
    },
    otherSub: {
       items: []
    }
  }
}})

> ["brand", "group", "subGroup", "items", "otherSub", "items"]

And you can use it like so:

var lookingFor = ['brand', 'group', 'newGroup', 'newSubGroup']
var existings = getAttrs(obj)

var missings = []
var presents = []

lookingFor.forEach(attr => {
  if (existings.indexOf(attr) === -1) {
    missings.push(attr)
  } else { 
    presents.push(attr)
  }
})

Solution 3:

I wrote a function to recursively get unique keys from a nested object, then filtered the array of all the keys you mentioned checking which were present in the result of my function.

var thisObject = {
	brand: {
  		group: {
    		subGroup: {
       			items: []
    		},
    		otherSub: {
       			items: []
    		}
        }
  	}
};

var arr_full =  ['brand', 'group', 'newGroup', 'newSubGroup'] ;

var key_array = [];

function addToKeyArray( key_array, object ){
	
    for( var key in object ){
    
    	// only get unique keys
    	if( key_array.indexOf( key ) === -1 ){
        	key_array.push( key );
        }
    
    	// concat the result of calling this function recurrsively on object[key]
    	key_array.concat( addToKeyArray( key_array, object[key] ) );	
    }
    
    return key_array;
}


var test = addToKeyArray( [], thisObject );

var missing = arr_full.filter( function( el ) {
  return test.indexOf( el ) < 0;
});

console.log( test );
console.log( missing )

Solution 4:

You can create recursive function using for...in loop inside another function and return object as result..

var obj = {"brand":{"group":{"subGroup":{"items":[]},"otherSub":{"items":[]}}}}
var keys =  ['brand', 'group', 'newGroup', 'newSubGroup'] ;

function findKeys(data, keys) {
  keys = keys.slice();
  
  function findPresent(data, keys) {
    var result = []
    
    for(var i in data) {
      if(typeof data[i] == 'object') result.push(...findPresent(data[i], keys))
      var index = keys.indexOf(i);
      if(index != -1) result.push(...keys.splice(index, 1))
    }
    
    return result
  }
  
  return {present: findPresent(data, keys), missing: keys}
}

console.log(findKeys(obj, keys))

Solution 5:

To keep things clean and readable you can use "for in", inside a nested function for your recursion.

function recur(obj) {
  let preMiss = {
    present: [],
    missing: []
  }
  let root = traverse => {
    for (let key in traverse) {
      if (Array.isArray(traverse[key].items)) {
        preMiss.missing.push(key);
      }
      if (typeof traverse[key] === 'object' && !Array.isArray(traverse[key].items)) {
        preMiss.present.push(key);
        root(traverse[key])
      }
    }
  }
  root(obj);
  return preMiss;
}

const object = {
  brand: {
    group: {
      subGroup: {
        items: []
      },
      otherSub: {
        items: []
      }
    }
  }
}


console.log(Object.entries(recur(object)));

Post a Comment for "Recursively Find Keys On An Object"