
API 返回的 json 数据: [ { id: 3, post: 73, parent: 2 }, { id: 2, post: 73, parent: 0 } ]
目标是: [ { id: 2, post: 73, parent: 0, children: [ { id: 3, post: 73, parent: 2 } ], } ]
这是我写的递归(在微信小程序的 util.js 里): function rebuildArray(data = [], parent = 0) { var rebuildData = [];
for (var i = 0; i < data.length; i++) { if (data[i].parent === parent) { data[i]['children'] = data[i]; } else { rebuildArray(data[i], data[i].parent); } rebuildData = data[i]; } return rebuildData; }
但是结果是错误的。。。
我改了一下逻辑,每次循环data,判断当前数组parent为0时,赋值给rebuildData,否则,如果当前数组parent等于函数的传值parent时,把当前数组push到rebuildData里,否则进行下一次循环,如下,但是我在小程序里运行时,他报错提示Cannot read property 'push' of undefined。。。
function rebuildArray (data = [], parent = 0) { if (data === null) { return; } var rebuildData = {}; for (var i = 0; i < data.length; i++) { if (data[i].parent == 0){ rebuildData[i] = data[i]; } else { if (data[i].parent === parent) { rebuildData[i].push({'children': data[i]}); } else { rebuildArray(data, data[i].parent); } } } return rebuildData; } 这是我最后的解决方案,无奈只能用两个函数来实现:
const getSOnsTree= function (obj, data) { var children = new Array(); for (var i = 0; i < data.length; i++) { if (data[i].parent == obj.id) { getSonsTree(data[i], data); children.push(data[i]); } } if (children.length > 0) { obj.children = children; } return obj; } const buildTree = function (data = {}) { var ptree = []; for (var i = 0; i < data.length; i++) { if (data[i].parent === 0) { var o = getSonsTree(data[i], data); ptree.push(o); } } return ptree; } 然后把后端返回 json 放进 buildTree 里就行了: console.log(buildTree(data));
实现了 。。。
1 per 2017-12-03 18:04:01 +08:00 如果数据里面有一条数据, 它既不是某一项的 child, 也不是某一项的 parent. 你要怎么处理? |
2 s609926202 OP @per 不会出现这种情况的,我这个源数据是评论数据,,只有要么是顶级数据,要是是节点下的回复数据,也就是说 parent 不为 0 |
3 geelaw 2017-12-03 18:17:46 +08:00 我的神呐……您这个效率太低了,而且明明有非常简单的高效写法的。 第一步给所有的元素加上 .children = [] 第二步按照 id 排序 第三步把每个元素 push 进它 parent 的 children 里面 第四步删除每个 children 为空数组的元素的 children 属性,并顺便把其他的元素收集起来 时间是 nlogn。 此外,您的代码没有贴对,让人很难受。 |
4 longear 2017-12-03 19:26:38 +08:00 下面这两行的逻辑不对,parent 只是一个数字, 按照你的逻辑 只要相等,就让 data[i] 的 children 指向自身,这就说不通, 输出结果自然不对。 if (data[i].parent === parent) { data[i]['children'] = data[i]; 可以分解为两三个独立的函数,逻上就简单很多。 |
5 longear 2017-12-03 19:36:21 +08:00 var apiData = [ { id: 3, post: 73, parent: 2 }, { id: 2, post: 73, parent: 0 } ]; function findParent(data, parent){ for(var i=0; i<data.length; i++){ if(data[i].id == parent){ return data[i]; } } return []; } function preProcess(data){ for (var i = 0; i < data.length; i++) { findParent(data, data[i].parent)['children'] = data[i]; } } function rebuildArray(data = [], parent = 0) { for (var i = 0; i < data.length; i++) { if(data[i]['parent'] == 0){ // 找到根元算 return data[i]; } } } preProcess(apiData); console.log(rebuildArray(apiData)); |
6 luguokong 2017-12-03 19:54:03 +08:00 var rebuildData = {}; 对象没有 push 方法 |
7 s609926202 OP @luguokong 改成[]也报同样的错,,, |
8 lwbjing 2017-12-04 09:31:21 +08:00 哥你没发现你的方法一执行,你的对象就重置了吗。。 |
9 s609926202 OP @lwbjing 确实,,如果是 php 就好了,,还有引用 |
10 s609926202 OP 这是我最后的解决方案,无奈只能用两个函数来实现: ``` const getSOnsTree= function (obj, data) { var children = new Array(); for (var i = 0; i < data.length; i++) { if (data[i].parent == obj.id) { getSonsTree(data[i], data); children.push(data[i]); } } if (children.length > 0) { obj.children = children; } return obj; } const buildTree = function (data = {}) { var ptree = []; for (var i = 0; i < data.length; i++) { if (data[i].parent === 0) { var o = getSonsTree(data[i], data); ptree.push(o); } } return ptree; } ``` 然后把后端返回 json 放进 buildTree 里就行了: ``` console.log(buildTree(data)); ``` 实现了 。。。 |