文档章节

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

 甜酒0917
发布于 2016/12/01 13:57
字数 651
阅读 38
收藏 0
点赞 0
评论 0

递归实现(保存对象属性值,并添加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[n].levelOnTheTree=getLevelOnTheTree(ary,data[n]);
      if(temp>0){
        data[n].children=_initDomTreeObject(ary,data[n].children?data[n].children:[]);
    if(data[n].children.length==0){
      delete data[n].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)

 

© 著作权归作者所有

共有 人打赏支持
粉丝 1
博文 12
码字总数 3354
作品 0
武汉
JavaScript 编程精解 中文第三版 十二、项目:编程语言

十二、项目:编程语言 原文:Project: A Programming Language 译者:飞龙 协议:CC BY-NC-SA 4.0 自豪地采用谷歌翻译 部分参考了《JavaScript 编程精解(第 2 版)》 确定编程语言中的表达式...

ApacheCN_飞龙 ⋅ 05/11 ⋅ 0

从JS对象开始,谈一谈“不可变数据”和函数式编程

文章转载自:https://segmentfault.com/a/1190000008780076 作为前端开发者,你会感受到JS中对象(Object)这个概念的强大。我们说“JS中一切皆对象”。最核心的特性,例如从String,到数组,再...

朱先忠老师 ⋅ 05/20 ⋅ 0

深入框架本源系列 —— Virtual Dom

该系列会逐步更新,完整的讲解目前主流框架中底层相通的技术,接下来的代码内容都会更新在 这里 为什么需要 Virtual Dom 众所周知,操作 DOM 是很耗费性能的一件事情,既然如此,我们可以考虑...

夕阳 ⋅ 06/02 ⋅ 0

JavaScript 编程精解 中文第三版 十四、文档对象模型

十四、文档对象模型 原文:The Document Object Model 译者:飞龙 协议:CC BY-NC-SA 4.0 自豪地采用谷歌翻译 部分参考了《JavaScript 编程精解(第 2 版)》 Too bad! Same old story! Onc...

ApacheCN_飞龙 ⋅ 05/11 ⋅ 0

精读《你不知道的javascript》中卷

前言 《你不知道的 javascript》是一个前端学习必读的系列,让不求甚解的JavaScript开发者迎难而上,深入语言内部,弄清楚JavaScript每一个零部件的用途。本书《你不知道的javascript》中卷介...

程序员解决师 ⋅ 06/20 ⋅ 0

六种排序算法的JavaScript实现以及总结

最近几天在系统的复习排序算法,之前都没有系统性的学习过,也没有留下过什么笔记,所以很快就忘了,这次好好地学习一下。 首先说明为了减少限制,以下代码通通运行于Node V8引擎而非浏览器,...

DM.Zhong ⋅ 05/24 ⋅ 0

JavaScript 二叉搜索树以及实现翻转二叉树

本文包括:二叉搜索树(创建、遍历、搜索、插入等)、JavaScript 实现翻转二叉树 欢迎关注我的:个人博客、Github。 什么是二叉树? 二叉树的定义:二叉树的每个结点至多只有二棵子树(不存在...

CaiJinyc ⋅ 06/10 ⋅ 0

JavaScript 工作原理之十一-渲染引擎及性能优化小技巧

原文请查阅这里,略有删减,本文采用知识共享署名 4.0 国际许可协议共享,BY Troland。 本系列持续更新中,Github 地址请查阅这里。 这是 JavaScript 工作原理的第十一章。 迄今为止,之前的...

tristan ⋅ 06/17 ⋅ 0

前端要以正确的姿势学习编译原理(上篇)

前端要以正确的姿势学习编译原理(上篇) 发布于 02:05 文章被以下专栏收录

brambles ⋅ 05/22 ⋅ 0

深入学习JavaScript函数

前言: 函数对于任何一门语言来说都是核心的概念,通过函数可以封装任意多条语句,而且可以在任何地方、任何时候调用执行。而JavaScript中最好的特性就是它对函数的实现。它几乎无所不能。但...

云中玉卷 ⋅ 05/02 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

mysql5.7系列修改root默认密码

操作系统为centos7 64 1、修改 /etc/my.cnf,在 [mysqld] 小节下添加一行:skip-grant-tables=1 这一行配置让 mysqld 启动时不对密码进行验证 2、重启 mysqld 服务:systemctl restart mysql...

sskill ⋅ 昨天 ⋅ 0

Intellij IDEA神器常用技巧六-Debug详解

在调试代码的时候,你的项目得debug模式启动,也就是点那个绿色的甲虫启动服务器,然后,就可以在代码里面断点调试啦。下面不要在意,这个快捷键具体是啥,因为,这个keymap是可以自己配置的...

Mkeeper ⋅ 昨天 ⋅ 0

zip压缩工具、tar打包、打包并压缩

zip 支持压缩目录 1.在/tmp/目录下创建目录(study_zip)及文件 root@yolks1 study_zip]# !treetree 11└── 2 └── 3 └── test_zip.txt2 directories, 1 file 2.yum...

蛋黄Yolks ⋅ 昨天 ⋅ 0

聊聊HystrixThreadPool

序 本文主要研究一下HystrixThreadPool HystrixThreadPool hystrix-core-1.5.12-sources.jar!/com/netflix/hystrix/HystrixThreadPool.java /** * ThreadPool used to executed {@link Hys......

go4it ⋅ 昨天 ⋅ 0

容器之上传镜像到Docker hub

Docker hub在国内可以访问,首先要创建一个账号,这个后面会用到,我是用126邮箱注册的。 1. docker login List-1 Username不能使用你注册的邮箱,要用使用注册时用的username;要输入密码 ...

汉斯-冯-拉特 ⋅ 昨天 ⋅ 0

SpringBoot简单使用ehcache

1,SpringBoot版本 2.0.3.RELEASE ①,pom.xml <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.3.RELE......

暗中观察 ⋅ 昨天 ⋅ 0

监控各项服务

比如有三个服务, 为了减少故障时间,增加监控任务,使用linux的 crontab 实现. 步骤: 1,每个服务写一个ping接口 监控如下内容: 1,HouseServer 是否正常运行,所以需要增加一个ping的接口 ; http...

黄威 ⋅ 昨天 ⋅ 0

Spring源码解析(八)——实例创建(下)

前言 来到实例创建的最后一节,前面已经将一个实例通过不同方式(工厂方法、构造器注入、默认构造器)给创建出来了,下面我们要对创建出来的实例进行一些“加工”处理。 源码解读 回顾下之前...

MarvelCode ⋅ 昨天 ⋅ 0

nodejs __proto__跟prototype

前言 nodejs中完全没有class的这个概念,这点跟PHP,JAVA等面向对象的语言很不一样,没有class跟object的区分,那么nodejs是怎么样实现继承的呢? 对象 对象是由属性跟方法组成的一个东西,就...

Ai5tbb ⋅ 昨天 ⋅ 0

Ubuntu16.04 PHP7.0 不能用MYSQLi方式连接MySQL5.7数据库

Q: Ubuntu16.04 PHP7.0 不能用MYSQLi方式连接MySQL5.7数据库 A: 执行以下2条命令解决: apt-get install php-mysql service apache2 restart php -m 执行后会多以下4个模块: mysqli mysqlnd...

SamXIAO ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部