2013-02-21 43 views
8

Jak mogę utworzyć zamek Clojure dla TRIE, reprezentowany przez zagnieżdżone mapy, były klucze są litery.?Clojure Zipper zagnieżdżonych map represyjnych TRIE

coś takiego:

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

Reprezentuje Trie z 2 słów 'banana' i 'Ana'. (Jeśli to konieczne, możliwe jest wprowadzenie pewnych zmian na mapach).

Próbowałem przekazać map? vals assoc jako 3 funkcje do zamka błyskawicznego, odpowiednio. Ale to nie działa.

Jakie 3 funkcje należy użyć?

A jak wyglądałaby wkładka do triety na podstawie zamka?

Odpowiedz

14

map?vals#(zipmap (keys %1) %2) zrobiłby, ale nie obsługuje wstawiania/usuwania dzieci (ponieważ dzieci są tylko wartościami, nie wiesz, który klucz do usunięcia/dodania).

Poniższe map-zipper obsługuje wstawianie/usuwanie, ponieważ węzły są parami [k v] (z wyjątkiem katalogu głównego, który jest mapą).

(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

Dodałem to do ClojureDocs i pod warunkiem, link do tej odpowiedzi. Mam nadzieję, że jest OK. http://clojuredocs.org/clojure.zip/zipper#example_54d91161e4b081e022073c72 – muhuk

0

solution proposed by @cgrant jest wielki, ale pośrednio opisuje drzewo gdzie wszystkie gałęzie i węzły liściowe mają przypisaną wartość (klawisz w słowniku), z wyjątkiem węzła głównego, który jest tylko gałęzią bez wartości. Drzewo {"/" nil} nie jest drzewem z pojedynczym węzłem, ale drzewem z anonimową gałęzią root i pojedynczym węzłem o wartości /. W praktyce oznacza to, że każde przejście drzewa musi najpierw wykonać (zip/down t), aby zejść do węzła głównego.

Alternatywnym rozwiązaniem jest jawne modelowanie korzenia na mapie, to znaczy tworzenie suwaków z map za pomocą jednego klucza w katalogu głównym. Na przykład: {"/" {"etc/" {"hosts" nil}}}

Suwak może być następnie wdrożona w:

(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."))))