2014-11-29 18 views
5

Biorąc pod uwagę mapę z kluczem: treść, gdzie zawartość jest listą ciągów lub innych map, w jaki sposób mogę spłaszczyć wartości, aby otrzymać tylko ciągi znaków?Clojure - Rekurencyjne spłaszczanie zagnieżdżonych map

(flattener {:content '("b" {:content ("c" {:content ("d")})} "e")}) 

> '("b" "c" "d" "e") 

Potykam się przez bardzo hacky powtarzające się pętle i teraz mój mózg jest wypalony. Czy istnieje ładny idiomatyczny sposób na zrobienie tego w Clojure?

Dzięki.

Co mam jest poniżej, a mimo to działa, to dość brzydki

(defn flatten-content 
    [coll] 
    (loop [acc '(), l coll] 
    (let [fst (first l), rst (rest l)] 
     (cond 
     (empty? l) (reverse acc) 
     (seq? fst) (recur acc (concat fst rst)) 
     (associative? fst) (recur acc (concat (:content fst) rst)) 
     :else (recur (conj acc fst) rst))))) 

Odpowiedz

8

Funkcja tree-seq pomaga chodzić, ponieważ mapy

(def m {:content '("b" {:content ("c" {:content ("d")})} "e")}) 

zawsze ma listę " dzieci "z kluczem :content, działa

(filter string? (tree-seq associative? :content m)) 
;=> ("b" "c" "d" "e") 
+0

Dość trudno przebić do elegancji. Dzięki. – Scott

5

Th e Poniższa funkcja rekurencyjna działa (i jest o 25% szybsza niż filter ed tree-seq podejścia):

(defn flatten-content [node] 
    (lazy-seq 
    (if (string? node) 
     (list node) 
     (mapcat flatten-content (:content node))))) 
Powiązane problemy