如何创建一个Clojure的拉链的TRIE,通过嵌套的地图来表示,分别键是字母?
事情是这样的:
{\b {\a {\n {\a {\n {\a {'$ '$}}}}}} \a {\n {\a {'$ '$}}}}
代表与2个字“香蕉”和“语录”特里树。 (如果必要的话,它可能作出一些变化在这里的地图。)
我试图通过map? vals assoc
map? vals assoc
分别作为3种功能的拉链。 但它似乎没有工作..
我应该使用什么样的3个功能?
而如何插入 - 到 - 特里会是什么样基于拉链?
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))
该由@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."))))