后话: 现有新的实现方案,基于java8 Stream ,不妨看下?
使用java8中Stream轻松遍历树形结构
一切都源于项目需求。近期web项目中需要这样的功能:将json数据转为树级结构,json的数据结构如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 [ { "id" : "1" , "pId" : "0" , "value" : "水电站项目" }, { "id" : "2" , "pId" : "1" , "value" : "项目一标段" }, { "id" : "3" , "pId" : "1" , "value" : "项目二标段" } ]
于是开始百度,找到如下解决方案:
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 function toTree (data ) { data.forEach (function (item ) { delete item.children ; }); var map = {}; data.forEach (function (item ) { map[item.id ] = item; }); var val = []; data.forEach (function (item ) { var parent = map[item.pId ]; if (parent) { (parent.children || (parent.children = [])).push (item); } else { val.push (item); } }); return val; }
这个方案却也适合,只是他只能适用于 id-pId
这种,要适配 其他 像 dataId-parentId
这种就需要将上面代码中的 id
改为dataId
,pId
改为parentId
。
之后又发现了另一种方案。
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 function transData (a, idStr, pidStr, chindrenStr ){ var r = [], hash = {}, id = idStr, pid = pidStr, children = chindrenStr, i = 0 , j = 0 , len = a.length ; for (; i < len; i++){ hash[a[i][id]] = a[i]; } for (; j < len; j++){ var aVal = a[j], hashVP = hash[aVal[pid]]; if (hashVP){ !hashVP[children] && (hashVP[children] = []); hashVP[children].push (aVal); }else { r.push (aVal); } } return r; }
来自:json转树状结构(js)
这样使用:var jsonDataTree = transData(jsonData, 'id', 'pid', 'chindren');
,其中 参数一是json数据对象,后三个参数分别指明了 id
、 pId
以及其子集 chindren
,很好解决了方案一的不足.
借于方案二的启发,何不将方案一改造改造,于是就有了:
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 34 35 36 37 38 function toTree (data,idStr="id" ,pIdStr="pId" ,chindrenStr="children" ) { data.forEach (function (item ) { delete item[chindrenStr]; }); var map = {}; data.forEach (function (item ) { map[item[idStr]] = item; }); var val = []; data.forEach (function (item ) { var parent = map[item[pIdStr]]; if (parent) { (parent[chindrenStr] || (parent[chindrenStr] = [])).push (item); } else { val.push (item); } }); return val; }
其中后三个参数设置默认值分别是 id-pId-children
,像开题的那段json刚好满足就省略后三个参数可以这样调用:
1 2 3 4 var jsonData = eval ('[{"id":"1","pId":"0","value":"水电站项目"},{"id":"2","pId":"1","value":"项目一标段"},{"id":"3","pId":"1","value":"项目二标段"}]' ); var jsonDataTree = toTree (jsonData); console .log (jsonDataTree);
输出如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [ { "id" : "1" , "pId" : "0" , "value" : "水电站项目" , "children" : [ { "id" : "2" , "pId" : "1" , "value" : "项目一标段" }, { "id" : "3" , "pId" : "1" , "value" : "项目二标段" } ] } ]
参考