Converting map keys to nested namespace keys
Code
;; namespaced_keys.clj
(defn keyword-name [k]
(clojure.string/replace (str (str k)) ":" ""))
(defn name-space
([nsp m]
(if (map? m)
(reduce
(fn [acc [k v]]
(assoc acc (keyword (keyword-name nsp) (keyword-name k)) v)) {} m)
{nsp m}))
([m]
(if (map? m)
(let [map-keys (keys m)
map-vals (vals m)]
(apply merge (map name-space map-keys map-vals)))
m)))
;; https://dnaeon.github.io/clojure-map-ks-paths/
(defn keys-in
"Returns a sequence of all key paths in a given map using DFS walk."
[m]
(letfn [(children [node]
(let [v (get-in m node)]
(if (map? v)
(map (fn [x] (conj node x)) (keys v))
[])))
(branch? [node] (-> (children node) seq boolean))]
(->> (keys m)
(map vector)
(mapcat #(tree-seq branch? children %)))))
(defn map-depth [m]
(apply max (map count (keys-in m))))
(defn deep-name-space
([m depth]
(if (< depth 1)
m
(recur (name-space m) (dec depth))))
([m]
(deep-name-space m (dec (map-depth m)))))
;;;;;;;;;;;;;;;;;;;;;;;;
;; Examples
;;;;;;;;;;;;;;;;;;;;;;;;
(keyword-name :user/a)
;;=> "user/a"
(name :user/a)
;;=> "a"
(defn some-fn [nsp acc k v]
(assoc acc (keyword (keyword-name nsp) (keyword-name k)) v))
(some-fn :user {} :a 1)
;;=> #:user{:a 1}
(keys (some-fn :user {} :a 1))
;;=> (:user/a)
(defn some-fn-with-defaults [acc key-val]
(let [k (first (keys key-val))
v (first (vals key-val))]
(some-fn :user acc k v)))
(some-fn-with-defaults {} {:a 1})
;;=> #:user{:a 1}
(reduce some-fn-with-defaults {} [{:a 1} {:b 2}])
;;=> #:user{:a 1, :b 2}
(name-space :user "john")
;;=> {:user "john"}
(name-space :user {:a 1})
;;=> #:user{:a 1}
(name-space :user {:a 1 :b 2})
;;=> #:user{:a 1, :b 2}
(name-space :user {:a 1 :b {:c 2}})
;;=> #:user{:a 1, :b {:c 2}}
(name-space
(name-space :user {:a 1 :b {:c 2}}))
;;=> {:user/a 1, :user/b/c 2}
(deep-name-space {:user {:a 1 :b {:c 2}}} 1)
;;=> #:user{:a 1, :b {:c 2}}
(deep-name-space {:user {:a 1 :b {:c 2}}} 2)
;;=> {:user/a 1, :user/b/c 2}
(keys-in {:user {:a 1 :b {:c 2}}})
;;=> ([:user] [:user :a] [:user :b] [:user :b :c])
(map-depth {:user {:a 1 :b {:c 2}}})
;;=> 3
(deep-name-space {:user {:a 1 :b {:c 2}}})
;;=> {:user/a 1, :user/b/c 2}
(def deep-ns-map
(deep-name-space {:user {:a 1 :b {:c 2}}}))
deep-ns-map
;;=> {:user/a 1, :user/b/c 2}
(last (keys deep-ns-map))
;;=> :user/b/c
(get deep-ns-map (last (keys deep-ns-map)))
;;=> 2
(:user/b/c deep-ns-map)
;;=> nil
(type :user/b/c)
;;=> clojure.lang.Keyword
(get deep-ns-map :user/b/c)
;;=> nil
(get deep-ns-map (keyword "user/b/c"))
;;=> nil