递归
递归算法在日常工作中算是用的比较多的一种,比如DOM树的遍历,多层级树状结构的生成,遍历寻找某个树节点等
1 先来看下数据结构
var result = {
id:0,
name:"张飞",
item:[
{id:1,name:"关羽"},
{id:2,name:"刘备",item:[
{id:5,name:"荀彧"},
{id:6,name:"关平"}
]},
{id:3,name:"曹操"},
{id:4,name:"貂蝉"},
]
}
一般情况下后台返回类似于如上的嵌套数据结构,或者说只得到一部分数据,点击某个子节点,异步加载节点,异步加载之后的数据可能如下:
var result = {
id:0,
name:"张飞",
item:[
{id:1,name:"关羽"},
{id:2,name:"刘备",item:[
{id:5,name:"荀彧"},
{id:6,name:"关平"}
]},
//点击曹操这一项,加载出来刘禅和周仓,点击周仓,又异步加载项羽和别姬
{id:3,name:"曹操",item:[
{id:8,name:"刘禅"},
{id:9,name:"周仓",item:[
{id:10,name:"项羽"},
{id:11,name:"别姬"}
]}
]},
{id:4,name:"貂蝉"},
]
}
//点击曹操,返回如下数组
[
{id:8,name:"刘禅"},
{id:9,name:"周仓"}
]
//点击周仓,返回如下数组
[
{id:8,name:"项羽"},
{id:9,name:"别姬"}
]
2 如何实现项目中的需求
以目前我做的一个react项目为例:需求是
- 将类似于这样的数据以树状结构展示出来
- 异步加载子节点的数据,有可能是加载子节点,有可能是加载同级节点
- 所以就需要定位到每次点击的节点的位置,然后根据其他属性判断如何添加节点
- 关键就是如何通过递归找到对应id的节点位置
我的实现思路就是维持一个state状态对象,每次异步请求回来的数据,根据返回的id来判断点击的位置,进而将数据添加到state中对应的id位置中
3 代码实现递归
var item = [result]
//设置一个全局的value,存放找到对应item的时候的引用地址
var value = null ;
//函数要有返回值,否则默认返回undefiend
function getName(item,id){
if(!item) return null ;
for (var i = 0 ;i<item.length;i++){
if(item[i].id == id) {
value = item[i]
break ;
};
if(item[i].item){
getName(item[i].item,id)
};
}
return value ;
}
//可以试着改变id看下效果,最好打下断电,可以更加深刻的了解下程序运行的过程
var foundName = getName(item,7);
console.log('foundName',foundName)
如果想要更加的通用一些,可以稍加优化一下
var item = [result]
function getName(item,id){
let value = null ;
let ret = recurision(item,id);
return ret ;
function recurision(item,id){
if(!item) return null ;
for (var i = 0 ;i<item.length;i++){
if(item[i].id == id) {
value = item[i]
break ;
};
if(item[i].item){
recurision(item[i].item,id)
};
}
return value;
}
}
var foundName = getName(item,9);
console.log('foundName',foundName)
以上代码实现递归的核心思路是依靠声明一个外部的变量,递归函数内部进行查找,如果找到对应的item,则将此item赋值给value,递归函数返回改value值;
总感觉代码还不够简洁,大家有好的思路欢迎随时交流。
jimwmg@foxmail.com