0

I have declared a triple nested object, like so:

var food = {
    "fruit": {
        "apples": {
            "redApples": 20,
            "greenApples": 30
        },
        "bananas": {
            "yellowBananas": 10
        }
    },
    "grains": {
        "bread": {
            "brownBread": 50
        }
    }
};

I found this question, which worked for iterating through an object of an object, but I'm stuck. How would I iterate through this object?

Update: For this specific problem, nested for-loops would work fine, like this:

for(var key in food)
    for(var prop in food[key])
        for(var foo in food[key][prop])
            console.log(food[key][prop][foo]);

However, there are some good recursive functions below which would do this for indefinitely nested objects.

Community
  • 1
  • 1
Jared Nielsen
  • 3,669
  • 9
  • 25
  • 36
  • 5
    Put the code into a function that calls itself recursively. – Martin Smith May 12 '13 at 14:55
  • You need an abstracted solution (working for "infinitely" nested objects) or simply an example about how to iterate all keys / values in this specific object? – sixFingers May 12 '13 at 15:02
  • What's wrong with just using nested loops (you need one level more than in the question you found). Since it's not indefinitely nested, but exactly 3 levels, there's no need for recursion. – Bergi May 12 '13 at 15:42
  • possible duplicate of [Traverse all the Nodes of a JSON Object Tree with JavaScript](http://stackoverflow.com/questions/722668/traverse-all-the-nodes-of-a-json-object-tree-with-javascript) – TheHippo Feb 18 '14 at 11:59

3 Answers3

4

Martin is right, recursive function is the approach. Your function should check is the attribute an object. If it is - function must walk deeper by calling itself also, but with a nested object.

function recursiveIter(obj){
    for (var i in obj){
        if (typeof obj[i]=="object"){
            recursiveIter(obj[i]);
        }
        else {
            $('.ins').append(obj[i]);  // or what do you want to do with that           
        }
    }
}

recursiveIter(food);

jsfiddle with this approach.

georg
  • 211,518
  • 52
  • 313
  • 390
I159
  • 29,741
  • 31
  • 97
  • 132
1

You can create a general function which accepts an object and a callback then does a recursive call.

function objectWalk (obj, callback){
    for(o in obj){
        if(typeof obj[o] === 'object'){
            objectWalk(obj[o], callback);
        }else {
            callback(obj[o]);
        }
    }
}

What I'm doing here is looping through the object and checking if each item in the loop is an object. If it is, call the same function again. If not, pass the value of the object into a callback. Its a handy little function.

See it in action here.

Jim Hall
  • 6,079
  • 2
  • 16
  • 15
1

Like this?

walk = function(obj, fn, key) {
    if(typeof obj != "object")
        return fn(obj, key)
    for(var p in obj)
        if(obj.hasOwnProperty(p))
            walk(obj[p], fn, p)
}

or in a more concise way with ES5 functions:

walk = function(obj, fn, key) {
    return obj === Object(obj) ? 
        Object.keys(obj).forEach(function(p) { walk(obj[p], fn, p) }) : 
        fn(obj, key);
}

Example:

var food = {
    "fruit": {
        "apples": {
            "redApples": 20,
            "greenApples": 30
        },
        "bananas": {
            "yellowBananas": 10
        }
    },
    "grains": {
        "bread": {
            "brownBread": 50
        }
    }
};

walk(food, console.log.bind(console))

Result:

20 "redApples"
30 "greenApples"
10 "yellowBananas"
50 "brownBread"
georg
  • 211,518
  • 52
  • 313
  • 390