嵌套地图Clojure的拉链抑制特里树(Clojure Zipper of nested Maps

2019-07-20 07:58发布

如何创建一个Clojure的拉链的TRIE,通过嵌套的地图来表示,分别键是字母?

事情是这样的:

{\b {\a {\n {\a {\n {\a {'$ '$}}}}}} \a {\n {\a {'$ '$}}}}

代表与2个字“香蕉”和“语录”特里树。 (如果必要的话,它可能作出一些变化在这里的地图。)

我试图通过map? vals assoc map? vals assoc分别作为3种功能的拉链。 但它似乎没有工作..

我应该使用什么样的3个功能?

而如何插入 - 到 - 特里会是什么样基于拉链?

Answer 1:

map? vals #(zipmap (keys %1) %2)会做,但不支持插入/删除儿童(因为儿童是唯一的价值,你不知道删除/添加了哪个键)。

所述map-zipper下面不支持的插入/取出,因为节点[KV]双(除了其为图中的根目录)。

(defn map-zipper [m]
  (z/zipper 
    (fn [x] (or (map? x) (map? (nth x 1))))
    (fn [x] (seq (if (map? x) x (nth x 1))))
    (fn [x children] 
      (if (map? x) 
        (into {} children) 
        (assoc x 1 (into {} children))))
    m))


Answer 2:

该由@cgrant提出的解决方案是伟大的,但含蓄地描述了一棵树,所有分支和叶节点有除外只是一个分支,而不值根节点的相关值(在字典中的键)。 因此,树{"/" nil} ,是不是具有单个叶节点树,但与匿名根分支树,并用值的单个叶节点/ 。 在实践中,这意味着该树的每个遍历必须首先执行(zip/down t)以下降根节点。

一种替代的解决方案是根明确建模的图,即,仅与在根的单个密钥创建从地图拉链内部。 例如: {"/" {"etc/" {"hosts" nil}}}

拉链然后可以实现:

(defn map-zipper [map-or-pair]
  "Define a zipper data-structure to navigate trees represented as nested dictionaries."
  (if (or (and (map? map-or-pair) (= 1 (count map-or-pair))) (and (= 2 (count map-or-pair))))
    (let [pair (if (map? map-or-pair) (first (seq map-or-pair)) map-or-pair)]
      (zip/zipper
        (fn [x] (map? (nth x 1)))
        (fn [x] (seq (nth x 1)))
        (fn [x children] (assoc x 1 (into {} children)))
        pair))
    (throw (Exception. "Input must be a map with a single root node or a pair."))))


文章来源: Clojure Zipper of nested Maps repressing a TRIE