关于 Javascript 递归问题,我懵逼了,,,

2017-12-03 17:42:28 +08:00
 s609926202

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;

}

但是结果是错误的。。。

2598 次点击
所在节点    问与答
10 条回复
per
2017-12-03 18:04:01 +08:00
如果数据里面有一条数据, 它既不是某一项的 child, 也不是某一项的 parent. 你要怎么处理?
s609926202
2017-12-03 18:10:02 +08:00
@per 不会出现这种情况的,我这个源数据是评论数据,,只有要么是顶级数据,要是是节点下的回复数据,也就是说 parent 不为 0
geelaw
2017-12-03 18:17:46 +08:00
我的神呐……您这个效率太低了,而且明明有非常简单的高效写法的。

第一步给所有的元素加上 .children = []
第二步按照 id 排序
第三步把每个元素 push 进它 parent 的 children 里面
第四步删除每个 children 为空数组的元素的 children 属性,并顺便把其他的元素收集起来

时间是 nlogn。

此外,您的代码没有贴对,让人很难受。
longear
2017-12-03 19:26:38 +08:00
下面这两行的逻辑不对,parent 只是一个数字, 按照你的逻辑 只要相等,就让 data[i] 的 children 指向自身,这就说不通, 输出结果自然不对。
if (data[i].parent === parent) {
data[i]['children'] = data[i];


可以分解为两三个独立的函数,逻辑上就简单很多。
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));
luguokong
2017-12-03 19:54:03 +08:00
var rebuildData = {};
对象没有 push 方法
s609926202
2017-12-03 20:08:29 +08:00
@luguokong 改成[]也报同样的错,,,
lwbjing
2017-12-04 09:31:21 +08:00
哥你没发现你的方法一执行,你的对象就重置了吗。。
s609926202
2017-12-04 09:54:19 +08:00
@lwbjing 确实,,如果是 php 就好了,,还有引用
s609926202
2017-12-04 22:03:45 +08:00
这是我最后的解决方案,无奈只能用两个函数来实现:
```
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));
```

实现了
。。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/411603

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX