2013-04-26 412 views
4

我正在处理可以有一个子类别对象数组的类别对象数组。棘手的部分是这个嵌套数据的深度是未知的(并且可以改变)。 (请参阅底部的示例。)我想要做的是将“轨迹”返回到类别对象,但我遇到各种困难。如何在递归函数中跳出循环?

理想情况下,findCategory('b4')会返回:['c1', 'd2', 'd3', 'b4'](请参阅示例)。

我认为我的问题是我正在解决由递归造成的嵌套循环问题。有时我会在我的路线中获得额外的类别,或者当我认为我已经爆发时,一些更深的嵌套类别最终会落在路径中。

其中一个结果可能如下所示。很明显,它并没有在b4处杀死循环,我不知道为什么结果会被发现两次。

b4 
FOUND 
["c1", "d2", "d3", "b4"] 
e2 
FOUND 
["c1", "d2", "d3", "b4", "e2"] 

如果你还可以给我看一个underscore.js版本的奖励。

JSFiddle Link这里...

// Start function 
function findCategory(categoryName) { 
    var trail = []; 
    var found = false; 

    function recurse(categoryAry) { 

     for (var i=0; i < categoryAry.length; i++) { 
      console.log(categoryAry[i].category); 
      trail.push(categoryAry[i].category); 

      // Found the category! 
      if ((categoryAry[i].category === categoryName) || found) { 
       console.log('FOUND'); 
       found = true; 
       console.log(trail); 
       break; 

      // Did not match... 
      } else { 

       // Are there children/sub-categories? YES 
       if (categoryAry[i].children.length > 0) { 

        console.log('recurse'); 
        recurse(categoryAry[i].children); 

       // NO 
       } else { 
        trail.pop(); 
        if (i === categoryAry.length - 1) { 
         trail.pop(); 
        } 
       } 
      } 

     } 
    } 

    return recurse(catalog); 
} 

console.clear(); 
console.log(findCategory('b4')); 

例如数组类别对象,具有类别对象的嵌套数组。假设嵌套深度未知。

var catalog = [ 
{ 
    category:"a1", 
    children:[ 
     { 
      category:"a2", 
      children:[] 
     }, 
     { 
      category:"b2", 
      children:[ 
       { 
        category:"a3", 
        children:[] 
       }, 
       { 
        category:"b3", 
        children:[] 
       } 
      ] 
     }, 
     { 
      category:"c2", 
      children:[] 
     } 
    ] 
}, 
{ 
    category:"b1", 
    children:[] 
}, 
{ 
    category:"c1", 
    children:[ 
     { 
      category:"d2", 
      children:[ 
       { 
        category:"c3", 
        children:[] 
       }, 
       { 
        category:"d3", 
        children:[ 
         { 
          category:"a4", 
          children:[] 
         }, 
         { 
          category:"b4", 
          children:[] 
         }, 
         { 
          category:"c4", 
          children:[] 
         }, 
         { 
          category:"d4", 
          children:[] 
         } 
        ] 
       } 
      ] 
     }, 
     { 
      category:"e2", 
      children:[ 
       { 
        category:"e3", 
        children:[] 
       } 
      ] 
     } 
    ] 
} 
]; 
+0

只是返回而不是再次调用函数而不是中断。 – 2013-04-26 03:53:31

+0

只需用'return'替换'break;'; – jmk2142 2013-04-26 03:55:56

+0

是的,这应该做的伎俩(我认为,没有注意到你有这些功能嵌套深两级...但如果你不想再次调用该函数,解决方案是不要调用它)。 – 2013-04-26 03:56:11

回答

15

尝试

function findCategory(categoryName) { 
    var trail = []; 
    var found = false; 

    function recurse(categoryAry) { 

     for (var i = 0; i < categoryAry.length; i++) { 
      trail.push(categoryAry[i].category); 

      // Found the category! 
      if ((categoryAry[i].category === categoryName)) { 
       found = true; 
       break; 

       // Did not match... 
      } else { 
       // Are there children/sub-categories? YES 
       if (categoryAry[i].children.length > 0) { 
        recurse(categoryAry[i].children); 
        if(found){ 
         break; 
        } 
       } 
      } 
      trail.pop(); 
     } 
    } 

    recurse(catalog); 

    return trail 
} 

演示:Fiddle

+1

不错,除了返回'trail'之外,你还有什么改变? – 2013-04-26 04:25:00

+1

这正是应该工作。如果递归函数调用找到匹配,它只需要一个标记标志来停止原始循环的运行,并且代码会执行该操作。 – 2013-04-26 04:25:09

+0

啊,我现在看到它。必须是时间睡觉;) – 2013-04-26 04:25:52

0

返回语句的工作,但请记住它会被称为每次循环解开这不是你在找什么。示例

// global scope 
String matchingVariable; 

int getMatch(index count, String input, String[] inputs){ 

    if(isValid(input) || count < inputs.length){ 
    // your condition is met and break 
    // assign your value to global scope variable 
    matchingVariable = input; 
    }else if(matchingVariable ==null){ 
    ++count 
    if(count < inputs.length){ 
     getMatch(count, input+inputs[count], inputs) 
    } 

    // NOTE RETURN - I WOULDN'T DO THIS 
    return input; 

    // doesn't work instead assign the input to global scope variable when a match is found. 
    } 

}