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 1
我的神呐……您这个效率太低了,而且明明有非常简单的高效写法的。
第一步给所有的元素加上 .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)); ``` 实现了 。。。 |