求优化一个代码。。搞了一天了

2017-08-08 15:41:34 +08:00
 vincenth520
var str = '[{"name":"a","description":"a","type":"string","son":[1]},{"name":"b","description":"b","son":[2],"type":"string"},{"name":"c","description":"v","son":[],"type":"string"},{"name":"d","description":"d","son":[],"type":"string"}]';

var values = JSON.parse(str);
var value = {};


values.forEach((item)=>{
	get(item,value);
})


function get(item,obj){
	if(item.son.length != 0){
		item.son.forEach((j)=>{
			obj[item.name] = {};
			get(values[j],obj[item.name]);
		})
	}else{
		obj[item.name] = {};
		value = Object.assign(value,obj);
	}
}

values.forEach((item)=>{
	if(item.son.length != 0){
		item.son.forEach((j)=>{
			delete value[values[j].name];
		})
	}
})

console.log(value)

如上代码,大致意思就是将这个 json 转为对象,然后根据 name 生成新的对象,代码没问题,运行一下就知道了,需要简化下,感觉写的很 low

4077 次点击
所在节点    JavaScript
17 条回复
blackywkl
2017-08-08 16:52:48 +08:00
用 map 或 reduce 吧
fulvaz
2017-08-08 17:04:30 +08:00
楼主你这样写代码会被打死的啊

```
obj[item.name] = {};
value = Object.assign(value,obj);
```

要么为啥要直接修改全局变量
jmc891205
2017-08-08 17:11:00 +08:00
你用递归来做的话 树的高度很大的时候会爆栈的吧
yeze322
2017-08-08 17:41:19 +08:00
本质上是一个重建多叉树问题。另外,你这个代码目测有 bug,get() 第三行,如果 b.son = [2, 3],只有 3 会写进去。起码应该这么些才算“没问题”
···
function get(item,obj){
obj[item.name] = {};
if(item.son.length != 0){
item.son.forEach((j)=>{
get(values[j],obj[item.name]);
})
}else{
value = Object.assign(value,obj);
}
}
···
shuson
2017-08-08 17:43:25 +08:00
读不懂题
vincenth520
2017-08-08 17:50:35 +08:00
@yeze322 是,如果键不同级重复的话是写不进去的。。。
vincenth520
2017-08-08 17:51:11 +08:00
@shuson 你运行一下你就应该知道是什么意思
vincenth520
2017-08-08 17:52:09 +08:00
@fulvaz 修改全局变量没啥大问题吧。。。
fulvaz
2017-08-08 18:05:22 +08:00
@vincenth520 额,问题挺大,尽可能写无副作用代码。
seki
2017-08-08 18:06:56 +08:00
感觉你需要 lodash
8qwe24657913
2017-08-08 18:47:49 +08:00
https://gist.github.com/8qwe24657913/e5f42dde7d279ce1534528b4570f9cfc#file-v2ex_381395-js

读楼主的代码比重写都难……写了两种,第二种和楼主代码行为一样
第一种与第二种的区别:
循环引用 [{"name":"a","son":[0]}] 第二种爆栈
对象唯一 [{"name":"a","son":[2]},{"name":"b","son":[2]},{"name":"c","son":[]}] 第二种 result.a.c !== result.b.c
需要哪种自取……
broker
2017-08-08 19:51:19 +08:00
首先理清思路,拆分出几个函数,这样便于理解和测试,后面再进行优化~
按理解写了一下,不过没有测试正确性~

var str = '[{"name":"a","description":"a","type":"string","son":[1]},{"name":"b","description":"b","son":[2],"type":"string"},{"name":"c","description":"v","son":[],"type":"string"},{"name":"d","description":"d","son":[],"type":"string"}]';

var values = [];
try {
values = JSON.parse(str);
} catch(ex) {
console.err(ex);
}
var value = {};

function getChildrenByIndex(index) {
var children = [];
var i = 0;

for (i = 0; i < values[index].son.length; i++) {
children.push(values[values[index].son[i]]);
}
return children;
}

function getRoots(values) {
var i = 0;
var ii = 0;
var roots = [];
var isRoot;

for (i = 0; i < values.length; i++) {
isRoot = true;

for (ii = 0; ii < values.length; ii++) {
if (i !== ii) {
if (values[ii].son.indexOf(i) !== -1) {
isRoot = false;
}
}
}
if(isRoot) {
roots.push(values[i]);
}
}
return roots;
}

function getNodeNameByIndex(index) {
return values[index].name;
}


function rebuild(roots) {
var i = 0;
var ii = 0;
var res = {};

for (i = 0; i < roots.length; i++) {
res[roots[i].name] = {};
for(ii = 0; ii < roots[i].son.length; ii++) {
res[roots[i].name][getNodeNameByIndex(roots[i].son[ii])]
= rebuild(getChildrenByIndex(roots[i].son[ii]));
}
}
return res;
}

var roots = getRoots(values);

console.log(rebuild(roots));
vincenth520
2017-08-09 09:38:31 +08:00
@8qwe24657913 虽然不是很能懂,但先感谢大神,自己逻辑思维有点差。。。
vincenth520
2017-08-09 09:38:56 +08:00
@broker 先感谢,再慢慢理解。。。
piku
2017-08-09 21:50:59 +08:00
我觉得问题在于你把 JSON 转成 obj 后,obj 要怎么拿去用。如果 json 的项目是一定的( item.name 可控),直接定义变量来存储岂不更省事
vincenth520
2017-08-10 10:13:08 +08:00
@piku 肯定不能直接定义 obj 了,不然也就不会这样做了
piku
2017-08-10 22:04:27 +08:00
我觉得结合上下文,应该有更好的实现方法或逻辑或算法。做这样复杂的嵌套调用,不太好

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

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

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

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

© 2021 V2EX