Clojure - Recursively smooth nested maps

Given a card with a key: content, where the content is a list of lines or other cards, how can I flatten values ​​to get only lines?

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

I stumble upon attempts to intercept hacker cycles, and now my brain is burned out. Is there a good idiomatic way to do this in Clojure?

Thanks.

What I have is below, and although it works, it is pretty ugly

 (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))))) 
+5
source share
2 answers

The tree-seq function helps walk, as well as your card

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

always has a list of "children" with the key :content , this works

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

The following recursive function works (and about 25% faster than the filter ed tree-seq method):

 (defn flatten-content [node] (lazy-seq (if (string? node) (list node) (mapcat flatten-content (:content node))))) 
+5
source

Source: https://habr.com/ru/post/1207958/


All Articles