有一个多行字符串,每行开头会用空格来表示它的层级关系,每间隔一层它的空格总数为2,如何将它转为json格式的树型数据?本文就跟大家分享下这个算法,欢迎各位感兴趣的开发者阅读本文。
例如有一个字符串:
const text = `
Language
JavaScript
TypeScript
NodeJS
HTML
Server
DataBase
MongoDB
System
Linux
Window
`;
将其转换为有层次结构的json数据后为:
{
"name":"root",
"children":[
{
"name":"Language",
"children":[
{
"name":"JavaScript",
"children":[
{
"name":"TypeScript"
},
{
"name":"NodeJS"
}
]
},
{
"name":"HTML"
}
]
},
{
"name":"Server",
"children":[
{
"name":"DataBase",
"children":[
{
"name":"MongoDB"
}
]
}
]
},
{
"name":"System",
"children":[
{
"name":"Linux"
},
{
"name":"Window"
}
]
}
]
}
乍一看,要对字符串进行处理,好像没有什么比较好的方法,理不出头绪。当我们遇到这种直接从数据结构出发想不出办法的问题时,这时可能就要换个思路了,能否将它转换为另一种数据结构呢?
审题后发现,我们需要的数据元素在字符串中总是独占一行的,那么我们就要对每一行进行处理,此时最好的方式就是将它切割成数组。
那么,我们就以换行符作为切割点来构造数组,如下所示:
[
"","Language"," JavaScript", " TypeScript"," NodeJS", " HTML","Server"," DataBase"," MongoDB","System"," Linux"," Window",""
]
观察数组中的每个元素后,我们发现最顶层的数据开头无空格,每间隔一层,开头就会多两个空格。按照从前往后的顺序依次读取数据,将后一个数据与其之前的数据进行比较,进而确定他们之间的层次关系。
分析到这里,相信很多开发者已经看出了这个比较方式满足了“后入先出”原则,因此,我们可以用栈来解决这个问题,如下所示:
image-20220923074054521
接下来,我们将每个元素逐一入栈,分析下它的过程。如下图所示,我们列举了部分元素的入栈比对过程,通过观察后,总结出了如下几条规律。
image-20220925084748469
注意:为了让读者更直观的看出规律,strStack栈中的元素用字符串直接代替了,实际上栈中存储的数据是一个对象,该对象包含了name属性和children属性。当前入栈元素也会构造成一个对象,得出栈顶元素(deepStack)与入栈元素空格总数的比对结果后,会将入栈元素对象放进栈顶元素(strStack)的children中。
经过上面的分析,我们已经得出了完整的实现思路,接下来我们来看下代码的实现。
/**
* 字符串转树结构
* @param text
* @constructor
*/
export function DataConversion(text: string): nodeObj {
const splitArr = text.split("\n");
const json = { name: "root" };
const strStack = new Stack();
const deepStack = new Stack();
strStack.push(json);
deepStack.push(-1);
for (let i = 0; i < splitArr.length; i++) {
let str = splitArr[i];
if (!str) continue;
// 获取空格总数
const len = str.lastIndexOf(" ") + 1;
str = str.replace(/\s/g, "");
const curObj = { name: str };
// 寻找当前入栈元素的父层级
while (len <= deepStack.peek()) {
deepStack.pop();
strStack.pop();
}
const stackTop: nodeObj = strStack.peek();
stackTop.children
? stackTop.children.push(curObj)
: (stackTop.children = [curObj]);
// 元素入栈,继续下一轮的比对
strStack.push(curObj);
deepStack.push(len);
}
return json;
}
注意:上述代码中声明了一个自定义类型
nodeObj
以及一个自定义类Stack
,完整代码请在示例代码中查看。
最后,我们将开头的例子代入上述代码中,校验下它能否正确解决问题。
const text = `
Language
JavaScript
TypeScript
NodeJS
HTML
Server
DataBase
MongoDB
System
Linux
Window
`;
const textJSON = DataConversion(text);
console.log(JSON.stringify(textJSON));
image-20220925095216309
image-20220925095349312
本文用到的代码完整版请移步:
至此,文章就分享完毕了。
我是神奇的程序员,一位前端开发工程师。
如果你对我感兴趣,请移步我的个人网站,进一步了解。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有