我有一个文本文件,其内容如下:
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进行操作?我发现很难对付 处理分层数据结构中处于中间状态。
答案 0 :(得分:1)
首先,您需要一个用于解析行的函数:
(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"}}}
请注意,没有缩进和内容格式错误的声明。