Search code examples
dictionaryrecursionclojurefunctional-programming

How can I get the nested keys of a map in clojure?


if my structure is

{ :a :A
  :b :B
  :c {
       :d :D
     }
  :e {
       :f {
            :g :G
            :h :H
          }
     }
}

I would like to get a function called keys-in that returns something like:

[[:a] [:b] [:c :d] [:e :f :g] [:e :f :h]]

so then I can do something like:

(not-any? nil? (map #(get-in my-other-map %1) (keys-in my-map)))

So I can be sure that my-other-map has the same keys that my-map


Solution

  • (defn keys-in [m]
      (if (map? m)
        (vec 
         (mapcat (fn [[k v]]
                   (let [sub (keys-in v)
                         nested (map #(into [k] %) (filter (comp not empty?) sub))]
                     (if (seq nested)
                       nested
                       [[k]])))
                 m))
        []))
    
    ;; tests
    user=> (keys-in nil)
    []
    user=> (keys-in {})
    []
    user=> (keys-in {:a 1 :b 2}))
    [[:a] [:b]]
    user=> (keys-in {:a {:b {:c 1}}})
    [[:a :b :c]]
    user=> (keys-in {:a {:b {:c 1}} :d {:e {:f 2}}})
    [[:a :b :c] [:d :e :f]]