簡體   English   中英

在Clojure中,如何從文本文件讀取分層數據結構?

[英]In Clojure, How to read a hierarchical data structure from a text file?

我有一個文本文件,其內容如下:

section1
    name=test
    value
        attr1=v1
        attr2=v2

section2
    age=20
    prop
        attr3=v3

我想讀取它,並將其呈現為樹數據結構(或JSON),例如:

{:section1
    {:name "test"
     :value {:attr1 "v1"
             :attr2 "v2" }}
 :section2
    {:age 20
     :prop {:attr3 "v3" }}
}

我如何在沒有額外lib的情況下使用核心clojure進行操作? 我發現在處理分層數據結構內很難處理中間狀態。

首先,您需要一個解析行的函數:

(defn parse-lines [s]
  (->> (clojure.string/split-lines s)
       (remove empty?)
       (map #(re-matches #"( *)([^ =]+)(?:=(.+))?" %))
       (map (fn [[_ level key value]]
              [(-> (or level "")
                   (count)
                   (quot 4))
               (keyword key)
               value]))))



(parse-lines content)
;; =>
([0 :section1 nil]
 [1 :name "test"]
 [1 :value nil]
 [2 :attr1 "v1"]
 [2 :attr2 "v2"]
 [0 :section2 nil]
 [1 :age "20"]
 [1 :prop nil]
 [2 :attr3 "v3"])

然后,您需要一個在行上遞歸迭代並創建嵌套映射的函數:

(defn reduce-lines [lines]
  (loop [[x & xs] lines
         path []
         prev-key nil
         result {}]
    (if-let [[l k v] x]
      (let [indent (- (count path) l)
            path (case indent
                   0 path
                   -1 (conj path prev-key)
                   (->> path (drop indent) vec))]
        (recur xs path k (assoc-in result (conj path k) v)))
      result)))



(reduce-lines (parse-lines content))
;; => 
{:section1 {:name "test", :value {:attr1 "v1", :attr2 "v2"}}, 
 :section2 {:age "20", :prop {:attr3 "v3"}}}

請注意,沒有縮進和內容格式錯誤的斷言。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM