Jon Harding
Jon Harding

Reputation: 4946

for each loop breaking before array complete

I have a simple function looks at an object in an array. If it doesn't find a match based on a property it checks if it has children and then checks each of those for a property value.

It seems to work as expected through the first object with children, however it is not hitting that third layer.

The object is something like this:

 data = [{
    title: 'Home',
    route: '/reports/home',
  },
  {
   title: 'Layer 2',
   children: [
     { title: 'Title 1', route: '/reports/title1' },
     { title: 'Title 2', route: '/reports/title2' },
   ],
  },
  {
    title: 'Layer 3',
    children: [
      { title: 'Title 3', route: '/reports/title3' },
      { title: 'Title 4', route: '/reports/title4' },
    ],
  }];


lookUpTitle = navGroup => {
  for (let item of navGroup) {
    if (item.route && item.route.toLowerCase() === '/reports/title3') {
      console.log(item.title)
      return item.title;
    } else {
      if (item.children) {
        return this.lookUpTitle(item.children);
      }
    }
  }
};
    
lookUpTitle(data)

I'm simply calling the function and passing in the array as above.

I can find Title 2 just fine, but the function will not iterate through to the third object in the array if I'm looking for Title 3 or 4. What am I missing?

Upvotes: 0

Views: 54

Answers (3)

DaveG
DaveG

Reputation: 455

If the for loop iterates thru an item that has children (as the 2nd one does) it will always return a value, exiting the for loop.

For the "else" clause, you need to check whether lookUpTitle actually found the desired title. If so, return it, if not, continue the for loop.

Upvotes: 0

SystemGlitch
SystemGlitch

Reputation: 2262

What is happening

To understand why the loop stops, let's write what is happening step by step:

  1. item takes the value of the first object. (Title = Home).
  2. The if condition is not met and item doesn't contain children
  3. item takes the value of the second object.
  4. The if condition is not met but item contains children
  5. The function returns the result of the function call lookUpTitle() thus the loop stops.
  6. Go back to step 1 but with the children values of your second object.

So the loop will always stop if an object doesn't meet the if condition and contains children.

How to fix it

In order to fix it, we have to track the recursive results. Check if a result is found through the recursive call of lookUpTitle(). If not, continue to loop, if found, you can return it. This method assumes you only want the first result found and not all existing results.

lookUpTitle = navGroup => {
  for (let item of navGroup) {
    if (item.route && item.route.toLowerCase() === '/reports/title3') {
      return item.title;
    } else {
      if (item.children) {
        var res = this.lookUpTitle(item.children);
        if(res != undefined)
          return res;
      }
    }
  }
};

Upvotes: 1

Pranay Rana
Pranay Rana

Reputation: 176956

there is problem , that is because of return

         if (item.children) {
            //from here it will come out as its return 
             return this.lookUpTitle(item.children);
          }

try like this

lookUpTitle = navGroup => {
      const title =[];
      for (let item of navGroup) {
        if (item.route && item.route.toLowerCase() === '/reports/title3') {
          console.log(item.title)
          return item.title;
        } else {
          if (item.children) {
            this.lookUpTitle(item.children);
          } else {
            console.log(item.title);
            return item.title;
          }
        }
      }
    };

Upvotes: 1

Related Questions