1 minute read

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

Updated: