我有一个文本文件,每行包含一个 json 值。我的文件如下:
{"id":"a","family":"root","parent":nil,"value":"valueofa"}
{"id":"b1","family":"b","parent":"a","value":"valueofb1"}
{"id":"c1","family":"c","parent":"b1","value":"valueofc1"}
{"id":"c2","family":"c","parent":"b1","value":"valueofc2"}
{"id":"b2","family":"b","parent":"root","value":"valueofb2"}
{"id":"d1","family":"d","parent":"b1","value":"valueofd1"}
Run Code Online (Sandbox Code Playgroud)
在上面给出的 json 中,我们的 family 属性表示一个层次结构,我们将“root”作为根,“b”作为“root”的孩子,“c”作为“b”和“d”的孩子也是“b”的孩子。
这个想法是遍历文件并在树中的适当位置添加正在读取的节点。一种方法是将这些条目读入“地图”,然后将此地图用于任何树操作。对于任何复杂的树操作,我不确定这将如何工作。很有可能根据某个要求,我可能必须将子项与现有父项分离并将其附加到另一个父项。显然 Clojure 拉链应该在这方面有所帮助,但我对拉链中节点的层次结构如何工作感到有些困惑。
如果有人能在这里指出我正确的方向,那就太好了。
这是几个问题,可能太宽泛了,但这里有一个示例。
如何读取文件?
(def file-contents (slurp "foo.txt"))`
Run Code Online (Sandbox Code Playgroud)如何将 JSON 转换为 Clojure 数据?
(require '[cheshire.core :refer [parse-string]])`
(def data (map #(parse-string % true)
(clojure.string/split file-contents #"\n")))
Run Code Online (Sandbox Code Playgroud)如何像树一样对待带有父引用的列表?
(require '[clojure.zip :as z])
(defn create-zipper [s]
(let [g (group-by :parent s)]
(z/zipper g #(map :id (g %)) nil (-> nil g first :id))))
(def t (create-zipper data))
Run Code Online (Sandbox Code Playgroud)
如何使用拉链?
user=> (-> t z/node)
"a"
user=> (-> t z/children)
("b1")
user=> (-> t z/down z/node)
"b1"
user=> (-> t z/down z/children)
("c1" "c2" "d1")
user=> (-> t z/down z/down z/rightmost z/node)
"d1"
Run Code Online (Sandbox Code Playgroud)