题目设定
在头脑简图中,软件能够将用户录入的文本直接转化为头脑导图。其规则是:用户录入的笔墨必需以一个感叹号作为一个节点的肇端标记,一个感叹号示意背面的笔墨处于第一级节点,两个感叹号示意背面的笔墨处于第二个节点,以此类推。
!内容
!!同盟会的政治纲要是“驱除鞑虏,恢复中华,竖立民国,平均地权”。
!!孙中山将同盟会的纲要归纳综合为三大主义,即民族主义、民权主义、民生主义,后被称为三民主义。
!!!民族主义,即民族反动,包括“驱除鞑虏,恢复中华”两项内容。
!!!民权主义即政治反动,内容是“竖立民国”,即竖立资产阶级民主共和国。
!!!民生主义即社会反动,指的是“平均地权”。
!评价:
!!它开端描绘出中国还不曾有过的资产阶级共和国计划,是一个比较完全而明白的资产阶级民主反动纲要。
!!对推进反动的生长产生了严重而主动的影响。
!!但它并非一个完全的资产阶级民主反动纲要。
所以, 上面这段笔墨经由软件处置惩罚后应当天生的树状图应当以下:
通例思绪
在将笔墨转化为图片的过程当中,如何将录入文本转化为一个构造化的数据至关重要。依据最轻易想到的思绪,算法设想应当是如许:
在全文的最末端加一个感叹号,然后找出一切处于单个感叹号之间的笔墨,放入一个数组中;
将数组中的第一个节点的笔墨提取出来,作为这个节点的title值保留下来,而且保留本身的父级的id(关于第一级的节点,父级节点id取-1),建立一个本身的id;
上述处置惩罚完毕以后,用递归的体式格局处置惩罚第二级、第三级……节点,直到悉数遍历完。
这就是我写初版顺序时的思绪,这个算法写得很笨,也写得很痛楚。层层递归的体式格局,在顺序调试时不那末相符地球人的头脑习惯。那种觉得很像是我们诟病Nodejs里的层层回调嵌套涌现的“殒命金字塔”式的顺序构造。
从新思索
前些天浏览过promise编程形式,很好的破解掉了这个“殒命金字塔”,让代码的构造异常便于浏览和调试。遭到这个启示,再次思索了这个算法的设想,应当有一个调试起来思绪更清晰,代码构造更一览无余的体式格局:
起首不斟酌感叹号的若干,把感叹号之间的笔墨提取出来,放入一个数组;
遍历数组,将数组中每一个元素建立为一个节点实例,实例包括以下属性:id, title, level, parent, childrenids。id即本身在数组中的序号,title为本身笔墨,level即本身笔墨中包括感叹号的数目。parent的算法稍庞杂:寻觅id和本身最接近且level比本身小1的节点,它的id即parent的值。childrenids临时设为一个空数组。
上一步遍历完成后,再次遍历,依据parent值将各个节点的childrenids数组填写好。
至此,一切节点的属性值已都具有。假如我们需要用一个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": []
}
]
}
]
}