嵌套地图的Clojure Zipper压制TRIE

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了嵌套地图的Clojure Zipper压制TRIE相关的知识,希望对你有一定的参考价值。

如何为嵌套地图表示的TRIE创建Clojure拉链,键是字母。

像这样的东西:

{ {a {
 {a {
 {a {'$ '$}}}}}} a {
 {a {'$ '$}}}}

代表一个带有2个单词'banana'和'ana'的trie。 (如有必要,可以在地图中进行一些更改..)

我试图分别将map? vals assoc作为拉链的3个函数传递给我。但它似乎没有工作..

我应该使用哪三种功能?

基于拉链,insert-into-trie的外观如何?

答案

map? vals #(zipmap (keys %1) %2)会做但不支持插入/删除孩子(因为孩子只是值,你不知道删除/添加哪个键)。

下面的map-zipper确实支持插入/删除,因为节点是[k v]对(除了作为映射的根)。

(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))
另一答案

solution proposed by @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压制TRIE的主要内容,如果未能解决你的问题,请参考以下文章

从嵌套地图(和矢量)创建 HTML 表格

在 Clojure 的嵌套映射中关联多个键/值的惯用方法是啥?

Clojure / Clojurescript:按多个值的地图分组

在 Clojure 中将嵌套向量减少为另一个向量

Clojure:将嵌套矢量格式应用于展平矢量

为啥 clojure 的地图在 println 中表现得那样?