一个将数据结构化的算法——以头脑简图为例

题目设定

在头脑简图中,软件能够将用户录入的文本直接转化为头脑导图。其规则是:用户录入的笔墨必需以一个感叹号作为一个节点的肇端标记,一个感叹号示意背面的笔墨处于第一级节点,两个感叹号示意背面的笔墨处于第二个节点,以此类推。

!内容
!!同盟会的政治纲要是“驱除鞑虏,恢复中华,竖立民国,平均地权”。
!!孙中山将同盟会的纲要归纳综合为三大主义,即民族主义、民权主义、民生主义,后被称为三民主义。
!!!民族主义,即民族反动,包括“驱除鞑虏,恢复中华”两项内容。
!!!民权主义即政治反动,内容是“竖立民国”,即竖立资产阶级民主共和国。
!!!民生主义即社会反动,指的是“平均地权”。
!评价:
!!它开端描绘出中国还不曾有过的资产阶级共和国计划,是一个比较完全而明白的资产阶级民主反动纲要。
!!对推进反动的生长产生了严重而主动的影响。
!!但它并非一个完全的资产阶级民主反动纲要。

所以, 上面这段笔墨经由软件处置惩罚后应当天生的树状图应当以下:

《一个将数据结构化的算法——以头脑简图为例》

通例思绪

在将笔墨转化为图片的过程当中,如何将录入文本转化为一个构造化的数据至关重要。依据最轻易想到的思绪,算法设想应当是如许:

  1. 在全文的最末端加一个感叹号,然后找出一切处于单个感叹号之间的笔墨,放入一个数组中;

  2. 将数组中的第一个节点的笔墨提取出来,作为这个节点的title值保留下来,而且保留本身的父级的id(关于第一级的节点,父级节点id取-1),建立一个本身的id;

  3. 上述处置惩罚完毕以后,用递归的体式格局处置惩罚第二级、第三级……节点,直到悉数遍历完。

这就是我写初版顺序时的思绪,这个算法写得很笨,也写得很痛楚。层层递归的体式格局,在顺序调试时不那末相符地球人的头脑习惯。那种觉得很像是我们诟病Nodejs里的层层回调嵌套涌现的“殒命金字塔”式的顺序构造。

从新思索

前些天浏览过promise编程形式,很好的破解掉了这个“殒命金字塔”,让代码的构造异常便于浏览和调试。遭到这个启示,再次思索了这个算法的设想,应当有一个调试起来思绪更清晰,代码构造更一览无余的体式格局:

  1. 起首不斟酌感叹号的若干,把感叹号之间的笔墨提取出来,放入一个数组;

  2. 遍历数组,将数组中每一个元素建立为一个节点实例,实例包括以下属性:id, title, level, parent, childrenids。id即本身在数组中的序号,title为本身笔墨,level即本身笔墨中包括感叹号的数目。parent的算法稍庞杂:寻觅id和本身最接近且level比本身小1的节点,它的id即parent的值。childrenids临时设为一个空数组。

  3. 上一步遍历完成后,再次遍历,依据parent值将各个节点的childrenids数组填写好。

  4. 至此,一切节点的属性值已都具有。假如我们需要用一个json来构造化的表达这一组数据,那末只需要再次遍历数组,建立一个json,将响应的值填充好就能够了。

下面是完成这个算法的代码:

var str="!内容 !!同盟会的政治纲要是“驱除鞑虏,恢复中华,竖立民国,平均地权”。 !!孙中山将同盟会的纲要归纳综合为三大主义,即民族主义、民权主义、民生主义,后被称为三民主义。 !!!民族主义,即民族反动,包括“驱除鞑虏,恢复中华”两项内容。 !!!民权主义即政治反动,内容是“竖立民国”,即竖立资产阶级民主共和国。 !!!民生主义即社会反动,指的是“平均地权”。 !评价: !!它开端描绘出中国还不曾有过的资产阶级共和国计划,是一个比较完全而明白的资产阶级民主反动纲要。!!对推进反动的生长产生了严重而主动的影响。 !!但它并非一个完全的资产阶级民主反动纲要。";


    //提取笔墨建立数组
    var pt=/!+[^!]+(?=!)/g;
    var arr=str.match(pt);
    console.log(arr)

    //遍历数组,将数组中每一个元素建立为一个节点实例
    var nodes=[];
    for(var i in arr){
        var obj={};
        obj.id=i;
        var len=arr[i].length;
        obj.title=arr[i].replace(/!/g,"");
        obj.level=len-obj.title.length;
        if(obj.level==1)obj.parent=-1;
        else obj.parent=findparent(obj.level,obj.id).id;
        obj.childrenids=[];
        nodes.push(obj);
    }

    //遍历数组,为每一个节点补上子节点鸠合
    for(var i in nodes){
        nodes[i].childrenids=findchildrenid(nodes[i].id);
    }

    //转化为json数组
    var json={
        title:"三民主义学说和资产阶级共和国计划",
        id:-1,
        parent:-1,
        level:-1,
        childrenids:findchildrenid(-1)
    }

    createjson(json,json.childrenids);

    function createjson(node,idarr){
        var c=[];
        for(var i in idarr){
            c.push(findbyid(idarr[i]));
        }
        node.children=c;

        for(var i in c){
            createjson(c[i],c[i].childrenids);
        }
    }

    console.log(JSON.stringify(json,null,"\t"))

    function findchildrenid(id){
        var arr=[];
        for(var i in nodes){
            if(nodes[i].parent==id)arr.push(nodes[i].id);
        }
        return arr;
    }

    function findparent(level,id){
        var parr=findbylevel(level-1);
        var n={},sub;
        for(var i in parr){
            if(parr[i].id<id){
                if(i==0 || id-parr[i].id<sub){
                    sub=id-parr[i].id;
                    n=parr[i];
                }
            }
        }
        return n;

    }

    function findbylevel(level){
        var arr=[];
        for(var i in nodes){
            if(nodes[i].level==level)arr.push(nodes[i]);
        }
        return arr;
    }

    function findbyid(id){
        for(var i in nodes)if(nodes[i].id==id)return nodes[i];
        return {};
    }

末了实行天生json的打印效果以下:

{
    "title": "三民主义学说和资产阶级共和国计划",
    "id": -1,
    "parent": -1,
    "level": -1,
    "childrenids": [
        "0",
        "6"
    ],
    "children": [
        {
            "id": "0",
            "title": "内容 ",
            "level": 1,
            "parent": -1,
            "childrenids": [
                "1",
                "2"
            ],
            "children": [
                {
                    "id": "1",
                    "title": "同盟会的政治纲要是“驱除鞑虏,恢复中华,竖立民国,平均地权”。 ",
                    "level": 2,
                    "parent": "0",
                    "childrenids": [],
                    "children": []
                },
                {
                    "id": "2",
                    "title": "孙中山将同盟会的纲要归纳综合为三大主义,即民族主义、民权主义、民生主义,后被称为三民主义。 ",
                    "level": 2,
                    "parent": "0",
                    "childrenids": [
                        "3",
                        "4",
                        "5"
                    ],
                    "children": [
                        {
                            "id": "3",
                            "title": "民族主义,即民族反动,包括“驱除鞑虏,恢复中华”两项内容。 ",
                            "level": 3,
                            "parent": "2",
                            "childrenids": [],
                            "children": []
                        },
                        {
                            "id": "4",
                            "title": "民权主义即政治反动,内容是“竖立民国”,即竖立资产阶级民主共和国。 ",
                            "level": 3,
                            "parent": "2",
                            "childrenids": [],
                            "children": []
                        },
                        {
                            "id": "5",
                            "title": "民生主义即社会反动,指的是“平均地权”。 ",
                            "level": 3,
                            "parent": "2",
                            "childrenids": [],
                            "children": []
                        }
                    ]
                }
            ]
        },
        {
            "id": "6",
            "title": "评价: ",
            "level": 1,
            "parent": -1,
            "childrenids": [
                "7",
                "8"
            ],
            "children": [
                {
                    "id": "7",
                    "title": "它开端描绘出中国还不曾有过的资产阶级共和国计划,是一个比较完全而明白的资产阶级民主反动纲要。",
                    "level": 2,
                    "parent": "6",
                    "childrenids": [],
                    "children": []
                },
                {
                    "id": "8",
                    "title": "对推进反动的生长产生了严重而主动的影响。 ",
                    "level": 2,
                    "parent": "6",
                    "childrenids": [],
                    "children": []
                }
            ]
        }
    ]
}
    原文作者:pitfall
    原文地址: https://segmentfault.com/a/1190000004166528
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞