在Clojure中获取树的密钥链
我想得到一棵树的钥匙链,从每一根到每一片叶子 例如,输入树:在Clojure中获取树的密钥链,clojure,Clojure,我想得到一棵树的钥匙链,从每一根到每一片叶子 例如,输入树: {"b" {:term true}, "a" {"y" {:term true}, "x" {:term true}}} 我期望的结果是: (("b" :term) ("a" "x" :term) ("a" "y" :term)) or ["b" "ax" "ay"] 我找到了一个尾部递归,它工作得很好: (defn down-strings [trie] "this one works. 80msecs for addre
{"b" {:term true}, "a" {"y" {:term true}, "x" {:term true}}}
我期望的结果是:
(("b" :term) ("a" "x" :term) ("a" "y" :term)) or ["b" "ax" "ay"]
我找到了一个尾部递归,它工作得很好:
(defn down-strings [trie]
"this one works. 80msecs for address.txt, not bad at all"
(lazy-seq
(loop [strings [],trie trie]
(if (empty? trie) strings
(let [[k v] (first trie)]
(recur (if (:term v) (conj strings k) strings)
(reduce
conj
(rest trie)
(map (fn [[dk dv]] [(str k dk) dv]) (dissoc v :term)))))))))
现在我的递归实践遇到了问题:
(defn down-strings [trie]
(if (map? trie)
(map (fn [[k v]] (conj (down-strings v) k)) trie)
[]))
输出为:
(("b" [:term]) ("a" ("y" [:term]) ("x" [:term])))
我尽了我所能,但没能解决这个问题
(defn down-strings
([trie] (down-strings trie []))
([trie prefix]
(if (map? trie)
(mapcat (fn [[k v]]
(down-strings v (conj prefix k)))
trie)
[prefix])))
递归解决方案更容易,使用一个额外的参数表示每个分支的累积状态,并且使用mapcat
确保每个路径都是一个序列,而不是序列的深度嵌套(路径中每个项的嵌套级别更高)。
`
比如说,
(down-strings {"b" {:term true}, "a" {"y" {:term true}, "x" {:term true}}})
;("ax" "ay" "b")
我预计这会比以前慢一点
#(让[[dk dv]][(clojure.string/join[k dk])dv])
写得更好,因为它与相同的(fn[[dk dv]][(str k dv)dv])
非常感谢。终于开始懂得如何递归思考了。如果您想要一个展平列表作为最终结果,那么每个迭代结束时的内部结果至少应该是一个展平列表!这就是我用“地图”失败的原因。再次感谢@Thumbnail!后来我发现每次“地图”把我弄得乱七八糟,“地图猫”就来救我。我应该更多地关注Clojure的seq。@Choulin确实关注解决方案。有很多技巧在展示。
(down-strings {"b" {:term true}, "a" {"y" {:term true}, "x" {:term true}}})
;("ax" "ay" "b")