Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find property by name in a deep object

I have a HUGE collection and I am looking for a property by key someplace inside the collection. What is a reliable way to get a list of references or full paths to all objects containing that key/index? I use jQuery and lodash if it helps and you can forget about infinite pointer recursion, this is a pure JSON response.

fn({ 'a': 1, 'b': 2, 'c': {'d':{'e':7}}}, "d");  // [o.c]  fn({ 'a': 1, 'b': 2, 'c': {'d':{'e':7}}}, "e"); // [o.c.d]  fn({ 'aa': 1, 'bb': 2, 'cc': {'d':{'x':9}}, dd:{'d':{'y':9}}}, 'd'); // [o.cc,o.cc.dd] 

fwiw lodash has a _.find function that will find nested objects that are two nests deep, but it seems to fail after that. (e.g. http://codepen.io/anon/pen/bnqyh)

like image 776
Shanimal Avatar asked Mar 26 '13 16:03

Shanimal


People also ask

How do I find out if an object has owned property?

The hasOwnProperty() method will check if an object contains a direct property and will return true or false if it exists or not. The hasOwnProperty() method will only return true for direct properties and not inherited properties from the prototype chain.

How do you find the key of an object?

There are mainly two methods to check the existence of a key in JavaScript Object. The first one is using “in operator” and the second one is using “hasOwnProperty() method”. Method 1: Using 'in' operator: The in operator returns a boolean value if the specified property is in the object.


2 Answers

This should do it:

function fn(obj, key) {     if (_.has(obj, key)) // or just (key in obj)         return [obj];     // elegant:     return _.flatten(_.map(obj, function(v) {         return typeof v == "object" ? fn(v, key) : [];     }), true);      // or efficient:     var res = [];     _.forEach(obj, function(v) {         if (typeof v == "object" && (v = fn(v, key)).length)             res.push.apply(res, v);     });     return res; } 
like image 110
Bergi Avatar answered Oct 19 '22 19:10

Bergi


a pure JavaScript solution would look like the following:

function findNested(obj, key, memo) {   var i,       proto = Object.prototype,       ts = proto.toString,       hasOwn = proto.hasOwnProperty.bind(obj);    if ('[object Array]' !== ts.call(memo)) memo = [];    for (i in obj) {     if (hasOwn(i)) {       if (i === key) {         memo.push(obj[i]);       } else if ('[object Array]' === ts.call(obj[i]) || '[object Object]' === ts.call(obj[i])) {         findNested(obj[i], key, memo);       }     }   }    return memo; } 

here's how you'd use this function:

findNested({'aa': 1, 'bb': 2, 'cc': {'d':{'x':9}}, dd:{'d':{'y':9}}}, 'd'); 

and the result would be:

[{x: 9}, {y: 9}] 
like image 32
Eugene Kuzmenko Avatar answered Oct 19 '22 20:10

Eugene Kuzmenko