在Clojure中获取一棵树的钥匙链

时间:2014-08-12 15:54:23

标签: 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 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])))

我尽我所能,无法解决这个问题。

2 个答案:

答案 0 :(得分:1)

(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的使用确保每个路径是一个序列,而不是序列的深层嵌套(额外的嵌套级别)每个学期的路径)。 `

答案 1 :(得分:1)

(defn down-strings [trie]
  (mapcat
    (fn [[k v]]
      (if (map? v) (map (partial str k) (down-strings v)) [""]))
    trie))

例如,

(down-strings {"b" {:term true}, "a" {"y" {:term true}, "x" {:term true}}})
;("ax" "ay" "b")

我希望这比@noisesmith's solution慢一点。