1. 程式人生 > >最近實現的一個分離文章內容功能,挺有意思,分享一下

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

速度 ## 所有 空字符串 產品需求 其他 tle 流程圖 可讀性

這個功能的描述是:

把一本符合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.5 小時。後者尤其快,下面我僅主要介紹後者的解決流程

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

輸出:

title[0] ===> "標題一" , content[0] ===> ""
title[0] ===> "標題二" , content[0] ===> "456789...."

流程圖

技術分享

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

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