TypeScript實(shí)現(xiàn)字符串轉(zhuǎn)樹結(jié)構(gòu)的方法詳解
前言
有一個多行字符串,每行開頭會用空格來表示它的層級關(guān)系,每間隔一層它的空格總數(shù)為2,如何將它轉(zhuǎn)為json格式的樹型數(shù)據(jù)?本文就跟大家分享下這個算法,歡迎各位感興趣的開發(fā)者閱讀本文。
例如有一個字符串:
const text = ` Language JavaScript TypeScript NodeJS HTML Server DataBase MongoDB System Linux Window `;
將其轉(zhuǎn)換為有層次結(jié)構(gòu)的json數(shù)據(jù)后為:
{ "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" } ] } ] }
思路分析
乍一看,要對字符串進(jìn)行處理,好像沒有什么比較好的方法,理不出頭緒。當(dāng)我們遇到這種直接從數(shù)據(jù)結(jié)構(gòu)出發(fā)想不出辦法的問題時,這時可能就要換個思路了,能否將它轉(zhuǎn)換為另一種數(shù)據(jù)結(jié)構(gòu)呢?
審題后發(fā)現(xiàn),我們需要的數(shù)據(jù)元素在字符串中總是獨(dú)占一行的,那么我們就要對每一行進(jìn)行處理,此時最好的方式就是將它切割成數(shù)組。
那么,我們就以換行符作為切割點(diǎn)來構(gòu)造數(shù)組,如下所示:
[ "","Language"," JavaScript", " TypeScript"," NodeJS", " HTML","Server"," DataBase"," MongoDB","System"," Linux"," Window","" ]
觀察數(shù)組中的每個元素后,我們發(fā)現(xiàn)最頂層的數(shù)據(jù)開頭無空格,每間隔一層,開頭就會多兩個空格。按照從前往后的順序依次讀取數(shù)據(jù),將后一個數(shù)據(jù)與其之前的數(shù)據(jù)進(jìn)行比較,進(jìn)而確定他們之間的層次關(guān)系。
分析到這里,相信很多開發(fā)者已經(jīng)看出了這個比較方式滿足了**“后入先出”**原則,因此,我們可以用棧來解決這個問題,如下所示:
- 準(zhǔn)備2個棧,一個用于存放每層的字符串,另一個用于存放每層的空格數(shù)
- 默認(rèn)將root入棧,將它的空格數(shù)定為-1
接下來,我們將每個元素逐一入棧,分析下它的過程。如下圖所示,我們列舉了部分元素的入棧比對過程,通過觀察后,總結(jié)出了如下幾條規(guī)律。
獲取入棧元素的空格總數(shù)
獲取棧頂(deepStack)元素,判斷入棧元素的空格總數(shù)是否大于棧頂元素。
- 滿足條件則獲取strStack的棧頂元素,將入棧元素元素放入它的子級
- 否則,將兩個棧的元素依次出棧。直至入棧元素的空格總數(shù)比deepStack的棧頂元素大,獲取strStack的棧頂元素,將入棧元素元素放入它的子級
將入棧元素以及它的空格總數(shù)分別放入對應(yīng)的棧中
直至所有元素都入棧比對完成,此問題得到解決
注意:為了讓讀者更直觀的看出規(guī)律,strStack棧中的元素用字符串直接代替了,實(shí)際上棧中存儲的數(shù)據(jù)是一個對象,該對象包含了name屬性和children屬性。當(dāng)前入棧元素也會構(gòu)造成一個對象,得出棧頂元素(deepStack)與入棧元素空格總數(shù)的比對結(jié)果后,會將入棧元素對象放進(jìn)棧頂元素(strStack)的children中。
實(shí)現(xiàn)代碼
經(jīng)過上面的分析,我們已經(jīng)得出了完整的實(shí)現(xiàn)思路,接下來我們來看下代碼的實(shí)現(xiàn)。
/** * 字符串轉(zhuǎn)樹結(jié)構(gòu) * @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; // 獲取空格總數(shù) const len = str.lastIndexOf(" ") + 1; str = str.replace(/\s/g, ""); const curObj = { name: str }; // 尋找當(dāng)前入棧元素的父層級 while (len <= deepStack.peek()) { deepStack.pop(); strStack.pop(); } const stackTop: nodeObj = strStack.peek(); stackTop.children ? stackTop.children.push(curObj) : (stackTop.children = [curObj]); // 元素入棧,繼續(xù)下一輪的比對 strStack.push(curObj); deepStack.push(len); } return json; }
注意:上述代碼中聲明了一個自定義類型nodeObj
以及一個自定義類Stack
,完整代碼請?jiān)谑纠a中查看。
最后,我們將開頭的例子代入上述代碼中,校驗(yàn)下它能否正確解決問題。
const text = ` Language JavaScript TypeScript NodeJS HTML Server DataBase MongoDB System Linux Window `; const textJSON = DataConversion(text); console.log(JSON.stringify(textJSON));
示例代碼
本文用到的代碼完整版請移步:
到此這篇關(guān)于TypeScript實(shí)現(xiàn)字符串轉(zhuǎn)樹結(jié)構(gòu)的方法詳解的文章就介紹到這了,更多相關(guān)TypeScript字符串轉(zhuǎn)樹結(jié)構(gòu)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Bootstrap基本插件學(xué)習(xí)筆記之按鈕(21)
這篇文章主要為大家詳細(xì)介紹了Bootstrap基本插件學(xué)習(xí)筆記之按鈕的相關(guān)資料,實(shí)現(xiàn)按鈕狀態(tài)控制等形式的交互,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-12-12IE中g(shù)etElementsByName()對有些元素?zé)o效的解決方案
這篇文章主要介紹了IE中g(shù)etElementsByName()對有些元素?zé)o效的解決方案,很簡單,很實(shí)用,需要的朋友可以參考下2014-09-09vue-router路由懶加載的實(shí)現(xiàn)(解決vue項(xiàng)目首次加載慢)
這篇文章主要介紹了vue-router路由懶加載的實(shí)現(xiàn)(解決vue項(xiàng)目首次加載慢),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-08-08Javascript生成器(Generator)的介紹與使用
這篇文章主要給大家介紹了關(guān)于Javascript生成器(Generator)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01JS實(shí)現(xiàn)的DOM插入節(jié)點(diǎn)操作示例
這篇文章主要介紹了JS實(shí)現(xiàn)的DOM插入節(jié)點(diǎn)操作,結(jié)合實(shí)例形式分析了javascript針對頁面dom元素動態(tài)操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2018-04-04JavaScript獲取網(wǎng)頁中第一個鏈接ID的方法
這篇文章主要介紹了JavaScript獲取網(wǎng)頁中第一個鏈接ID的方法,涉及javascript中document.links方法的使用,需要的朋友可以參考下2015-04-04