Skip to content

Instantly share code, notes, and snippets.

@NoamB
Last active May 15, 2019 18:03
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save NoamB/6e940775dfa63c73ee9c to your computer and use it in GitHub Desktop.
Save NoamB/6e940775dfa63c73ee9c to your computer and use it in GitHub Desktop.
camelize-dasherize mini library
(ns util.camelize-dasherize
(:import (clojure.lang IPersistentMap Keyword))
(:require [clojure.string :as s]
[clojure.zip :as zip]))
; TODO: regex is slow, should try iterating the string.
(defn dasherize-string
"Converts an underscored or camelized string
into an dasherized one."
[s]
(when s
(-> s
(s/replace #"([A-Z][a-z]+)" (fn [[match c]]
(if c (str "-" (s/lower-case c)) "")))
(s/replace #"([A-Z]+)" "-$1")
(s/replace #"[-_\s]+" "-")
(s/replace #"^-" ""))))
(defn camelize-string
"Converts a string from dash-case to camelCase."
[^String s]
(when s
(some-> s
(s/replace #"[-_\s]+(.)?"
(fn [[match c]]
(if c (s/upper-case c) ""))))))
;(time (dotimes [x 400000] (dasherize-keyword :clientOSVersion)))
;"Elapsed time: 915.063554 msecs"
(defn dasherize-keyword
[k]
(when k
(keyword (dasherize-string (name k)))))
;(time (dotimes [x 400000] (camelize-keyword :client-OS-version)))
;"Elapsed time: 537.186386 msecs"
(defn camelize-keyword
[k]
(when k
(keyword (camelize-string (name k)))))
(defn camelize-map-1 [m]
(into {} (map (fn [[k v]]
[(camelize-keyword k) v]) m)))
(defn dasherize-map-1 [m]
(into {} (map (fn [[k v]]
[(dasherize-keyword k) v]) m)))
(defn camelize-map-recur [m]
(into {} (map (fn [[k v]]
[(camelize-keyword k) (if (map? v) (camelize-map-recur v) v)]) m)))
(defn dasherize-map-recur [m]
(into {} (map (fn [[k v]]
[(dasherize-keyword k) (if (map? v) (dasherize-map-recur v) v)]) m)))
(defn map-zipper [m]
(zip/zipper
(fn [x] (or (map? x) (map? (nth x 1))))
(fn [x] (seq (if (map? x) x (nth x 1))))
(fn [x children]
(if (map? x)
(into {} children)
(assoc x 1 (into {} children))))
m))
(defn edit-map-keys-zip [m f]
(loop [loc (map-zipper m)]
(if (zip/end? loc)
(zip/root loc)
(recur (zip/next
(if (vector? (zip/node loc))
(zip/edit loc #(do [(f (first %)) (second %)]))
loc))))))
(defn camelize-map-zip [m]
(edit-map-keys-zip m camelize-keyword))
(defn dasherize-map-zip [m]
(edit-map-keys-zip m dasherize-keyword))
(defprotocol ICamelizable
(camelize [this]))
(defprotocol IDasherizable
(dasherize [this]))
(extend-protocol ICamelizable
String
(camelize [this]
(camelize-string this))
Keyword
(camelize [this]
(camelize-keyword this))
IPersistentMap
(camelize [this]
(camelize-map-zip this)))
(extend-protocol IDasherizable
String
(dasherize [this]
(dasherize-string this))
Keyword
(dasherize [this]
(dasherize-keyword this))
IPersistentMap
(dasherize [this]
(dasherize-map-zip this)))
@IliasDeros
Copy link

What is the difference between (s/replace #"([A-Z][a-z]+)" (fn [[match c]] (if c (str "-" (s/lower-case c)) ""))) and (s/lower-case s) ? The latter seems to do the same thing, but more simple

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment