描述資料最常見的結構是平面表格,資料庫,excel,csv都是典型的表格。表格是扁平結構,了解起來簡單,能友善的增删改查。
下面是一個典型的表格:
時間
小時
分鐘
12:03
12
03
15:32
15
32
從上面的表格,明顯能看出表格的缺陷:
所有的子項都是平級的,無法描述它們内在的結構
列名很重要,否則很難确定其語義,這和第一條相輔相成
在資料深度上進行規約和下鑽時,不可避免的會造成資料重複。
對列的描述,無法直接儲存在表格中,還需要另外建立資料結構存儲
如果我們将上面的表格描述成下面的樹,這些問題就變得容易解決了:
(父節點)
(子節點)12
(子節點):
(子節點)03
是以,父節點不需要存儲資料,其值是子節點資料的組合,不會有重複。能夠明确的描述資料的層級關系和結構,支援在不同層級檢索資料,對上面的例子,第一層是12:03, 細分之後,第二層是12和03。
是以,将表格轉換為樹,筆者将其稱為樹表,可能會是兩種情況:
結構一緻的樹的森林,每一棵樹代表一行資料
隻有一棵樹,每個樹節點是數組,分别對應了表格中的一列
推薦使用第二種,這樣就能友善地将列的元屬性記錄在節點中,而不造成重複,也可以很容易的将樹表打平,變成普通表格。樹結構是遞歸的,是以支援遞歸操作,下面将讨論樹表可能的操作類型。
對樹子節點的描述,通常有兩種:
将子節點作為數組,儲存在父節點中
将子節點儲存為連結清單,隻将頭結點儲存在父節點中
第二種方法的優點,比缺點多得多。第二種除了對子節點的索引通路不易之外,其他的操作都要比第一種友善。不用預先聲明長度,能友善地拼接,删除。
但最大的優點,是能夠友善的實作緩存機制。重複的資料,能讓多個節點指向同一個連結清單頭結點,實作複用。而第一種方案則會複雜得多。
是以,我們采用第二種政策作為樹表的存儲結構。
在不同節點讀取資料,值為子節點值的組合
在不同節點寫入資料,節點負責将資料配置設定到不同子節點存儲
删除一個節點,對應的子節點都會被删除
展平一個節點,将該節點替換為其子節點的頭結點
将節點拼接到其他子節點上
描述嵌套結構,子節點的下一個節點指向父節點。
同級節點的推導,如果父節點提供計算能力,則子節點能夠被計算并傳回結果
轉換為xml,json等遞歸結構類型
從html中自動提取樹表
這幾乎是樹表最正常的用途,随便看一個html的例子,資料都是以樹結構存儲的,沒有明确的列名,但其層級關系卻表現了資料的關聯性。
我們很難通過樹結構,自動标注“1997年建闆樓”的列名,但卻知道,它和“中樓層”屬于一個層級。這樣,自動清洗html就會友善地多。
資訊抽取
資訊抽取的結果,一般是樹,還是之前時間的例子,12:03提取子資訊後,就變成了12點和03分,分别成為了12:03的兩個子節點。
這也同樣避免了生成多個列,造成資料重複的問題。
自動推導
對編譯原理有概念的同學,自然會對文法樹有印象。文法樹代表了目前語句的邏輯結構,分析文法樹,能夠發現無用備援節點,或進行規約計算。例如加法(+)的父節點,如果有兩個int子節點,那麼就可以求和。
一樣的道理,如果在同一層級,分别有長度和寬度,那麼這兩個名額一般衡量的都是同一個“物體”,那麼自然就可以增加“面積”子節點。
同時,節點可以代表“動作”,也可以儲存函數,那麼樹表本身就提供了自動推導的能力。
節點的上浮/下沉,都可以通過規則自動實作,而之前對資料上鑽和下探,都可以了解為觀察樹不同的層級而已。
這極大地簡化了程式設計/推導,甚至能實作一個簡單的人工智能。
易于實作lazy執行
是否延遲執行,可根據實際要求來決定。如果父節點計算代價高昂,那麼可緩存子節點計算值,否則可随時傳回子節點的規約新值。
想要讓平面表支援延遲執行,肯定不會太容易。
資料就是對象
想象一下,以後通路一個資料表,都能通過object.property.subproperty來通路了,那種感覺多爽,還要什麼orm!
樹表最大的缺陷,是它對使用者不友好,了解扁平的表結構是很容易的,但如果看到一片森林,肯定不少程式員會暈菜,普通使用者更是不必說,是以這種審查資料的方式顯然隻應該在背景,面向程式員。
我們可以用excel等工具友善地檢視表結構,但樹表怎麼看?這也同樣需要可視化設計器,好在這種事情是苦力活,并不難做。
想象一下以後如何處理和清洗資料,把樹的某個節點拖到垃圾箱,這一列就自動删除了,可以建立某個層級的節點,然後添加幾個節點的連線,它就自動成了它們的父節點;節點和節點之間可以插入新的計算節點,定義新的層級。也可以随時檢視不同層級的資料,進而實作更好的洞察力。這一切簡直太酷了。
這個問題,确實是我在實際開發爬蟲和資料清洗工具時遇到的,平面表格大量的中間計算結果,重複列,無法定義的列名,讓我深感平面模式的弊端,我甚至都已經迫不及待地開發這樣的資料處理工具,以替代之前的工具。不過,在一切都不明朗之前,這種計劃還是往後推一推吧。
有任何問題,歡迎随時讨論。