最近實現的一個分離文章內容功能,挺有意思,分享一下

林冠巨集發表於2017-11-16

這個功能的描述是:

把一本符合markdown語法寫的書裡面的所有大章節裡面內容的每個大標題和該標題對應下的內容做分離,一 一對應。

一般會出現這種問題的場景:

  • 筆試演算法題
  • 產品需求

舉個例子,有一段內容是如下:

### 糖尿病的症狀 (這是 markdown 的第三級標題)
初期的症狀體現在.....複製程式碼

分離後要求達到:

title   ===> 糖尿病的症狀
content ===> 初期的症狀體現在...複製程式碼

對我而言,這個功能的目的是:

我們把一本書分割成上述的樣子,資料存入資料庫。供搜尋使用。搜尋方式,以 title 或 content 做模糊匹配,命中即返回。

相信看到這裡的讀者都能清楚知道上面談的是什麼,但願我的文字能通俗易懂,文字多了,我也記不住,累贅。

實現思路:

  • 正則匹配 ------------- ①
  • 逐行處理 ------------- ②

先談談正則匹配下的處理:

  • 優點
    • 寫好匹配式,其它交給 API,方便
  • 缺點
    • 難度大,上述問題的內容摻雜情況有很多種

然後是逐行處理處理:

  • 優點
    • 邏輯可控,可豐富自定義處理,例如過濾和二重分割,屬於完整的字串操作
    • 程式碼清晰,速度快一些
  • 缺點
    • 消耗記憶體多一些

兩種方法的對比:

  • 效率,平分
  • 可讀性,② > ①
  • 整體記憶體佔比,② > ①

舉個例子對比:

標題有下面的 markdown 程式碼形式:
###   第一種標題
####  第二種
##### 第三種[點我](http://www.xxx.com)
### ``第四種``
### <strong>第五種,巢狀html標籤</strong>
...複製程式碼
採用正規表示式處理的時候

對於上面的情況,第一次的正則拿出標題內容很簡單,例如這個: ###? 從三個#號開始貪婪匹配。這樣我們可以拿出標題,但是標題裡面還摻雜著一些其他標籤。你會想,有沒有可能在正則匹配就把摻雜的標籤去掉。那這個是肯定可以的,代價就是高超的正則匹配式子,且現在還沒考慮內容的情況。

為什麼非要去掉標籤呢? 因為這是標題,標題將會被用作搜尋的 key,且返回給前端的時候,你不能把這個解析符號也給前端對吧?去掉了有以下好處:

  • 減少搜尋的 o(n)
  • 方便顯示
採用逐行處理的時候

我們從檔案中讀出第一行 ### 第一種標題,replace 函式處理掉 ### 等符號,這裡迴圈處理即可去掉指定的任何符號。
讀出第三行的時候 ##### 第三種[點我](http://www.xxx.com),處理掉,##### [ ] ( 等,剩下就是完美:第三種點我

看到這,你是否覺得事情變簡單了?

我們知道 markdown 的非標題內容部分,符號和標籤更是多種多樣,如果我們用正則解決,假設標題能完美處理,那麼內容怎麼辦呢? > 如果去掉內容的其他無用標籤,或者要求特定儲存一些,等情況,多批次的正則過濾將會是花銷巨大的操作。

解決流程:

無論是正則匹配方案 還是 逐行處理方案,這兩種我都寫了對應的引擎函式,通過且以後者執行謂之0 bug。實現的時間加起來不足 3.4 小時。後者尤其快,下面我僅主要介紹後者的解決流程

先明確幾個細節點
  • 只有標題沒對應內容,自動補充為空字串
  • 只有內容沒對應標題,不錄入
例如
內容66655
####  標題一
####  標題二
456789....複製程式碼

輸出:

title[0] ===> "標題一" , content[0] ===> ""
title[1] ===> "標題二" , content[1] ===> "456789...."複製程式碼

流程圖

至此,已經很簡答,例如 Java 語言的 String API startWith 就能用在判斷是否是titleif(startWith"####")
過濾方面,replace 之類的函式,等都可以。公司程式碼,不便公開。

相關文章