从 json 中的文本文件创建一棵树 - Clojure

sc_*_*ray 2 tree json clojure

我有一个文本文件,每行包含一个 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 拉链应该在这方面有所帮助,但我对拉链中节点的层次结构如何工作感到有些困惑。

如果有人能在这里指出我正确的方向,那就太好了。

A. *_*ebb 5

这是几个问题,可能太宽泛了,但这里有一个示例。

  1. 如何读取文件?

    (def file-contents (slurp "foo.txt"))`
    
    Run Code Online (Sandbox Code Playgroud)
  2. 如何将 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)
  3. 如何像树一样对待带有父引用的列表?

    (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)

    了解如何将 seq 转换为树

  4. 如何使用拉链?

    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)