您的位置:首页 > Web前端 > JavaScript

js实现数组转树结构的递归与非递归实现

2016-12-01 00:00 363 查看
递归实现(保存对象属性值,并添加children和levelOnTheTree的属性)

function _initDomTreeObject(ary,data){
var data=data?data:(function(ary){
var tempAry=[];
var idList=[];
ary.forEach(function(item){idList.push(item.id)});
for(var i=0,len=ary.length;i<len;i++){
if(ary[i].pid==undefined||(ary[i].pid!=undefined&&deb(ary[i].pid,idList))){
var obj=ary[i];
tempAry.push(obj);
}
}
return tempAry;
}(ary));

function deb(id,idList){
var flag=true;
for(var ida in idList){
if(id==idList[ida]){
flag=false;
}
}
return flag;
}
function getParentNode(id,ary){
var parentNode;
ary.forEach(function(item){
if(item.id==id){
parentNode=item;
return false;
}
});
return parentNode;
}

function getLevelOnTheTree(ary,dataItem){
var idList=[];
ary.forEach(function(item){idList.push(item.id)});
var level=1;
while(!deb(dataItem.pid,idList)){
dataItem=getParentNode(dataItem.pid,ary)
level++;
}
return level;
}

var temp=0;
if(data.constructor==Array){
for(var i=0,len=data.length;i<len;i++){
for(var j=0,lenA=ary.length;j<lenA;j++){
if(ary[j].pid==data[i].id){
var obj=ary[j];
data[i].children=data[i].children||[];
data[i].children.unshift(obj);
temp++;
}
}
}
}

if(data.constructor==Array){
for(var n=0,lenB=data.length;n<lenB;n++){
data
.levelOnTheTree=getLevelOnTheTree(ary,data
);
if(temp>0){
data
.children=_initDomTreeObject(ary,data
.children?data
.children:[]);
if(data
.children.length==0){
delete data
.children;
}
}
}
}

return data;
}

非递归实现 (保存对象属性值,并添加children和levelOnTheTree的属性)

var aaa= [{name:'aaa',id:0},{name:'a',id:1},{name:'b',id:2,pid:1},{name:'c',id:3,pid:1},{name:'d',id:4,pid:2},{name:'e',id:5,pid:2}];

function _initDomTreeObject(sourceAry,data){
//保存原始数组,以便做比较(不修改原始数据)
var ary=[];
for(var i=0,len=sourceAry.length;i<len;i++){
ary[i]=sourceAry[i];
}
var data=data?data:(function(ary){
var tempAry=[];
var idList=[];
//取得一级菜单,兼容pid为空不存在等各种情况
ary.forEach(function(item){idList.push(item.id)});
for(var i=0,len=ary.length;i<len;i++){
if(ary[i].pid==undefined||(ary[i].pid!=undefined&&deb(ary[i].pid,idList))){
var obj=ary[i];
ary[i]=null;
//设定一级菜单的层次
obj.levelOnTheTree=getLevelOnTheTree(sourceAry,obj);
tempAry.push(obj);
}
}
return tempAry;
}(ary));
//内部方法,用来比较判断
function deb(id,idList){
var flag=true;
for(var ida in idList){
if(id==idList[ida]){
flag=false;
}
}
return flag;
}
//返回父亲节点
function getParentNode(id,ary){
var parentNode;
ary.forEach(function(item){
if(item.id==id){
parentNode=item;
return false;
}
});
return parentNode;
}
//通过循环判断结点的层次等级
function getLevelOnTheTree(ary,dataItem){
var idList=[];
ary.forEach(function(item){idList.push(item.id)});
var level=1;
while(!deb(dataItem.pid,idList)){
dataItem=getParentNode(dataItem.pid,ary)
level++;
}
return level;
}

//非递归的核心算法
function getSelfDom(itemAry,data){
var  flag=false;
var  len=data.length;

for(var i=0;i<data.length;i++){
console.log("长度",data.length)
if(itemAry.pid==data[i].id){
flag=true;
data[i].children=data[i].children||[];
//设置各节点的层次级别
itemAry.levelOnTheTree=getLevelOnTheTree(sourceAry,itemAry);
data[i].children.push(itemAry);
}else{
data[i].children&&(data=data.concat(data[i].children));

}

if(flag){
//如果有多个父亲,只找第一个父亲 ,不写此处的话兼容多父亲模式
break;
}
}
return {
flag:flag,
data:data.slice(0,len)
};
}

//非递归的循环出口
while(ary.length>0){
var itemAry=ary.shift();
if(itemAry!=null){
var obj=getSelfDom(itemAry,data);
if(obj.flag){
data=obj.data;
}else{
ary.push(itemAry);
}
}
}
return data;
}

var a=_initDomTreeObject(aaa);
console.log(a)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息