4

I am trying to find a value by key without knowing the object, include nested object, so the function will get a key and a object and return the value or undefined. This is my function:

/* Iterate over object and include sub objects */

function iterate (obj, key) {

    for (var property in obj) {
        if (obj.hasOwnProperty(property)) {
            //in case it is an object
            if (typeof obj[property] == "object") {
                if (obj.hasOwnProperty(key)) {
                    return obj[key]; //return the value 
                }
            }
            else {
                iterate(obj[property]);
            }
        }   
    }

    return undefined;
}

I call return inside a loop so it will be more efficient(hope so...).

1.is anyone have this function ready? this one does not work.

2.someone knows what to change to make it work?

Any help, including angular.js functions will be great.

Thanks.

felipeptcho
  • 1,377
  • 2
  • 9
  • 23
Itsik Mauyhas
  • 3,824
  • 14
  • 69
  • 114

3 Answers3

9

You reversed things a bit and you forgot to pass the second parameter to the recursive function call. Also, in this case there's no need to return undefined, because that is the default.

function iterate (obj, key) {
    var result;

    for (var property in obj) {
        if (obj.hasOwnProperty(property)) {
            // in case it is an object
            if (typeof obj[property] === "object") {
                result = iterate(obj[property], key);

                if (typeof result !== "undefined") {
                    return result;
                }
            }
            else if (property === key) {
                return obj[key]; // returns the value
            }
        }   
    }
}

EDIT: Actually, we should check if the property is equal to the key BEFORE checking if the value is an iterable object, in the case where we are looking for a key whose value is an object. Thanks to @Catinodeh!

function iterate (obj, key) {
    var result;

    for (var property in obj) {
        if (obj.hasOwnProperty(property)) {
            if (property === key) {
                return obj[key]; // returns the value
            }
            else if (typeof obj[property] === "object") {
                // in case it is an object
                result = iterate(obj[property], key);

                if (typeof result !== "undefined") {
                    return result;
                }
            }
        }   
    }
}
felipeptcho
  • 1,377
  • 2
  • 9
  • 23
  • It does not work for more then 2 levels if the value is leve1.leve2.key - it does not finds it. – Itsik Mauyhas Sep 21 '16 at 13:43
  • I just tested it with 5 levels, and it has found the key. `iterate({a: {b: {c: {d: {key: 3}}}}}, "key");` Please, provide a not working example. – felipeptcho Sep 21 '16 at 13:57
  • Yeah. It was wrong. I've updated the answer. Test it now, please. – felipeptcho Sep 21 '16 at 14:06
  • 1
    I would add "&& property !== key" to the second if in case you're looking for a key that IS an object. – Catinodeh Feb 19 '19 at 21:49
  • @Catinodeh The keys of an object cannot be objects, just String or Symbol. Even if you use Number as the key, it will be converted to String. – felipeptcho Feb 20 '19 at 19:26
  • 1
    @felipeptcho no, what I meant is that if the key you're looking for is an object, it will try to iterate its properties and not return it the moment it finds the key. – Catinodeh Mar 01 '19 at 03:41
  • @Catinodeh Oh yes! You're right! Nice catch! In this case, I think we can just invert the order of the `if` statements to check if the property is equal to the key BEFORE checking if the value is an iterable object. I'll update the answer. Thanks! – felipeptcho Mar 17 '19 at 15:22
1

Unflatten it first with the function that solved this problem: Fastest way to flatten / un-flatten nested JSON objects

and then simply use hasOwnProperty again

Community
  • 1
  • 1
Herr Derb
  • 4,977
  • 5
  • 34
  • 62
0

Here is a code snippet that worked for me. The assumption for me I was only searching nested objects, with no arrays.

function searcObject(obj, key){
        var found = false
        if(typeof obj == 'object' && obj !== null){
            Object.keys(obj).forEach(function(prop) {
                if(prop == key){
                    value = obj[key];
                    return true;
                } else{
                    searcObject(obj[prop], key);
                }
            });    
        } else {
            return false;
        }; 
    };
Wallace S.
  • 26
  • 4