之前对递归函数的理解还仅仅停留在书面,就是说从来没有在实际中用到过,不知道是运气好还是运气不好,做了这么久开发居然没碰到这种需求。不过倒是在jQuery
的源码里目睹了使用递归算法的地方,jQuery.extend
方法相信很多高玩都用过,用于拷贝对象,并且提供了深拷贝,这里的递归就是为了能够遍历对象内的对象内的对象内的对象…,这种数据我们总不能一直写下去把 😂,况且逻辑还是重复的。所以这里使用递归算法就巧妙的解决了这个问题。近日朋友在解决一个菜单搜索时遇到一个问题,这么个样子
需求是匹配到关键字的菜单及其子菜单显示出来,就是说只要当前的菜单项匹配到了,那子菜单也全部显示。
天真的我以为用个[].filter
函数就行了,直到我看到了数据是这样的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| [ { text: "菜单1", nodes: [ { text: "菜单1—菜单1" nodes: ... }, { text: "菜单1—菜单2" nodes: ... } ] }, { text: "菜单2", nodes: [ { text: "菜单2—菜单1" nodes: ... } ] } ]
|
就是说不知道菜单里有多少子菜单,所以去遍历就必须得用递归调用,将符合条件的菜单保留,好在最后解决了这个问题,下面贴出代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
function recursionSearch( arrayData, searchText ) { let newArray = []; arrayData = arrayData.nodes || arrayData for ( let i = 0, item; item = arrayData[ i++ ]; ) {
if ( item.text && item.text.indexOf( searchText ) > -1 ) { newArray.push( item ); } else { if ( item.nodes ) { let result = recursionSearch( item, searchText ); if ( result.length ) { item.nodes = result; newArray.push( item ) } } } } return newArray; }
|
结果终究是出来了,居然花了一个多小时,中间一度要放弃了,但是秉着“老司机”的光环坚持弄出来了,还是蛮开心的。令人汗颜的是花了这么久。(lll¬ω¬)
//-----------------更新----------------
如果这里需求变了,不再按照title来检索,而是检索disabled的项目,或者其他条件呢,上面的递归函数则需要变动一下,将检索条件开放出来由调用者自己来决定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| function recursionFilter( arrayData, filter ) { let newArray = []; arrayData = arrayData.nodes || arrayData for ( let i = 0, item; item = arrayData[ i++ ]; ) {
if ( filter( item ) ) { newArray.push( item ); } else { if ( item.nodes ) { let result = recursionFilter( item, filter ); if ( result.length ) { item.nodes = result; newArray.push( item ) } } } } return newArray; }
let result = recursionFilter( treeData, function( item ) { return item.state.check === true } )
|
filter
参数就是调用者传递的回调参数,执行的结果应该是一个boolean值来确定当前项目是否符合检索条件。