【问题标题】:Clojure Zipper of nested Maps repressing a TRIE嵌套地图的 Clojure 拉链压制 TRIE
【发布时间】:2013-02-07 10:30:44
【问题描述】:

如何为 TRIE 创建一个 Clojure 拉链,由嵌套映射表示,键是字母吗?

类似这样的:

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

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

我尝试将map? vals assoc 作为 3 个函数分别传递给拉链。 但它似乎不起作用..

我应该使用哪 3 个函数?

以及基于拉链的插入-trie 会是什么样子?

【问题讨论】:

    标签: clojure trie zipper


    【解决方案1】:

    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."))))
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-14
      • 1970-01-01
      • 2012-07-19
      • 2015-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-18
      相关资源
      最近更新 更多