clojurenested-map

Flatten Nested Map into List with Depth-First Search Ordering


In clojure, how can I turn a nested map like this:

{"1" {"1.1" {"1.1.1" {}
             "1.1.2" {}}
      "1.2" {}}
 "2" {"2.1" {}
      "2.2" {}
      "2.3" {}}}

Into this:

("1" "1.1" "1.1.1" "1.1.2" "1.2" "2" "2.1" "2.2" "2.3")

Solution

  • Here is a straightforward iterative solution (using loop and recur):

    (defn flatten-map [m]
      (loop [in m out []]
        (if-let [[[k v] & ts] (seq in)]
          (recur (concat v ts)
                 (conj out k))
          out)))
    

    And a "fancy" one (using tree-seq function)

    (defn flatten-map [m]
      (->> [nil m]
           (tree-seq sequential? second)
           (drop 1)
           (map first)))