2013-02-21 3 views
8

ネストされたマップで表現されたTRIEのClojureジッパーを、キーが文字であるように作成する方法を教えてください。ClojureネストされたマップのジッパーがTRIEを抑制する

このような何か:

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

は2つのワード 'バナナ' と 'ANA' とトライを表します。 (必要に応じて、地図上でここでいくつかの変更を加えることができます)

私はファンクションとしてmap? vals assocをジッパーに渡そうとしました。 しかし、それは動作しません..

どのような3つの関数を使用する必要がありますか?

ジッパーに基づいてインサートイントライがどのように見えるのですか?

答えて

14

map?vals#(zipmap (keys %1) %2)は子供の挿入/削除をサポートしていません(子供は値だけなので、削除/追加するキーはわかりません)。

ノードは[k v]のペア(マップであるルートを除く)であるため、以下のmap-zipperは挿入/削除をサポートしています。

(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)) 
+3

私はClojureDocsにこれを追加し、この回答へのリンクを提供します。私はそれが大丈夫だと思います。 http://clojuredocs.org/clojure.zip/zipper#example_54d91161e4b081e022073c72 – muhuk

0

solution proposed by @cgrantは素晴らしいですが、暗黙的にすべてのブランチとリーフノードは、値のないただの枝であるルート・ノード以外の関連する値(辞書内のキー)を持つツリーを説明しています。 したがって、ツリー{"/" nil}は、1つのリーフノードを持つツリーではなく、匿名ルートブランチと値が/の単一のリーフノードを持つツリーです。 実際には、ルートノードを下降させるためには、ツリーのすべてのトラバーサルが最初に(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.")))) 
関連する問題