Join the Stack Overflow Community
Stack Overflow is a community of 6.4 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

I'm trying to iterate through a nested object to retrieve a specific object identified by a string. In the sample object below, the identifier string is the "label" property. I can't wrap my head around how to iterate down through the tree to return the appropriate object. Any help or suggestions would be greatly appreciated.

var cars = 
    {
        label: 'Autos',
        subs:
            [
                {
                    label: 'SUVs',
                    subs: []
                },
                {
                    label: 'Trucks',
                    subs: [
                              {
                                label: '2 Wheel Drive',
                                subs: []
                              },
                              {
                                label: '4 Wheel Drive',
                                subs: [
                                          {
                                            label: 'Ford',                                        
                                            subs: []
                                          },
                                          {
                                            label: 'Chevrolet',
                                            subs: []                                      
                                          }
                                      ]                          
                              }
                          ]    
                },
                {
                    label: 'Sedan',
                    subs: []
                }
            ]
    }
share|improve this question
1  
possible duplicate of Traverse all the Nodes of a JSON Object Tree with JavaScript – Diodeus Nov 10 '11 at 19:15
    
You're wanting to search through all levels of the object for an arbitrary label? (Aha, traverse, that was the word I was looking for.) – Dave Nov 10 '11 at 19:16
    
Possible duplicate of Access / process (nested) objects, arrays or JSON – Liam Oct 20 at 15:29
up vote 22 down vote accepted

You can create a recursive function like this to do a depth-first traversal of the cars object.

var findObjectByLabel = function(obj, label) {
    if(obj.label === label) { return obj; }
    for(var i in obj) {
        if(obj.hasOwnProperty(i)){
            var foundLabel = findObjectByLabel(obj[i], label);
            if(foundLabel) { return foundLabel; }
        }
    }
    return null;
};

which can be called like so

findObjectByLabel(car, "Chevrolet");
share|improve this answer
    
In the original post, the sub-cars are not properties of the car object, but are contained in a subs array. – James Clark Nov 10 '11 at 19:35
    
@JamesClark I know. It should still work, and it is flexible in case he has more than one array property of if he decides to change the name of subs to something else. – Peter Olson Nov 10 '11 at 19:37
1  
Recursion is bad for very deep objects. You will get stack overflow. – Arjun U. Feb 9 '15 at 11:33
    
@ArjunU. It's fairly uncommon to have objects that are hundreds of levels deep. – Peter Olson Feb 9 '15 at 18:53
1  
@Vishal Without the obj.hasOwnProperty(i), custom prototype properties will be included. For example, if you define Array.prototype.first = function(a) { return a[0] }, then for(var i in []) will include the prototype property first. – Peter Olson Oct 10 '15 at 0:50

The following code assumes no circular references, and assumes subs is always an array (and not null in leaf nodes):

function find(haystack, needle) {
  if (haystack.label === needle) return haystack;
  for (var i = 0; i < haystack.subs.length; i ++) {
    var result = find(haystack.subs[i], needle);
    if (result) return result;
  }
  return null;
}
share|improve this answer

To increase performance for further tree manipulation is good to transform tree view into line collection view, like [obj1, obj2, obj3]. You can store parent-child object relations to easy navigate to parent/child scope.

Searching element inside collection is more efficient then find element inside tree (recursion, addition dynamic function creation, closure).

share|improve this answer

Try something like this:

cars.subs[0].subs[0].label

if you want to actually iterate you can do a for loop on each object in a recursive function and call that recursive function every time you hit the "subs" property of that object. This can cause issue though if you have a very deep object structure

share|improve this answer
    
This works only if you know the depth already, and that depth is exactly the same everywhere. – shoover Jul 14 '15 at 22:24

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.