V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
vincenth520
V2EX  ›  JavaScript

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

  •  
  •   vincenth520 · 2017-08-08 15:41:34 +08:00 · 4260 次点击
    这是一个创建于 2697 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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

    17 条回复    2017-08-10 22:04:27 +08:00
    blackywkl
        1
    blackywkl  
       2017-08-08 16:52:48 +08:00
    用 map 或 reduce 吧
    fulvaz
        2
    fulvaz  
       2017-08-08 17:04:30 +08:00
    楼主你这样写代码会被打死的啊

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

    要么为啥要直接修改全局变量
    jmc891205
        3
    jmc891205  
       2017-08-08 17:11:00 +08:00
    你用递归来做的话 树的高度很大的时候会爆栈的吧
    yeze322
        4
    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
        5
    shuson  
       2017-08-08 17:43:25 +08:00
    读不懂题
    vincenth520
        6
    vincenth520  
    OP
       2017-08-08 17:50:35 +08:00
    @yeze322 是,如果键不同级重复的话是写不进去的。。。
    vincenth520
        7
    vincenth520  
    OP
       2017-08-08 17:51:11 +08:00
    @shuson 你运行一下你就应该知道是什么意思
    vincenth520
        8
    vincenth520  
    OP
       2017-08-08 17:52:09 +08:00
    @fulvaz 修改全局变量没啥大问题吧。。。
    fulvaz
        9
    fulvaz  
       2017-08-08 18:05:22 +08:00
    @vincenth520 额,问题挺大,尽可能写无副作用代码。
    seki
        10
    seki  
       2017-08-08 18:06:56 +08:00
    感觉你需要 lodash
    8qwe24657913
        11
    8qwe24657913  
       2017-08-08 18:47:49 +08:00   ❤️ 1
    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
        12
    broker  
       2017-08-08 19:51:19 +08:00   ❤️ 1
    首先理清思路,拆分出几个函数,这样便于理解和测试,后面再进行优化~
    按理解写了一下,不过没有测试正确性~

    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
        13
    vincenth520  
    OP
       2017-08-09 09:38:31 +08:00
    @8qwe24657913 虽然不是很能懂,但先感谢大神,自己逻辑思维有点差。。。
    vincenth520
        14
    vincenth520  
    OP
       2017-08-09 09:38:56 +08:00
    @broker 先感谢,再慢慢理解。。。
    piku
        15
    piku  
       2017-08-09 21:50:59 +08:00 via Android
    我觉得问题在于你把 JSON 转成 obj 后,obj 要怎么拿去用。如果 json 的项目是一定的( item.name 可控),直接定义变量来存储岂不更省事
    vincenth520
        16
    vincenth520  
    OP
       2017-08-10 10:13:08 +08:00
    @piku 肯定不能直接定义 obj 了,不然也就不会这样做了
    piku
        17
    piku  
       2017-08-10 22:04:27 +08:00 via Android
    我觉得结合上下文,应该有更好的实现方法或逻辑或算法。做这样复杂的嵌套调用,不太好
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1024 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 20:30 · PVG 04:30 · LAX 12:30 · JFK 15:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.