嵌套地图的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的主要内容,如果未能解决你的问题,请参考以下文章
在 Clojure 的嵌套映射中关联多个键/值的惯用方法是啥?