Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a built-in function in Clojure to replace a character at a specific index in a string?

Tags:

clojure

e.g. I want to replace a character at index 2 in string "123456789" with character 'X'. I know that I can do something like (str (subs "123456789" 0 2) "X" (subs "123456789" 3)) but I want to know if there is already a built-in library function for this.

like image 985
hithacker Avatar asked Dec 19 '22 17:12

hithacker


1 Answers

another way, is to use java's StringBuilder, which has this exact api, and should be probably faster, than subs or vec (and obviously faster in case you do a number of changes at once):

user> (let [sb (StringBuilder. "123456789")]
        (str (.replace sb 1 2 "x")))
"1x3456789"

multiple changes:

user> (let [sb (StringBuilder. "123456789")]
        (doseq [idx [1 3 5]]
          (.replace sb idx (inc idx) "x"))
        (str sb))
"1x3x5x789"

a little performance benchmark:

user> (defn replace-builder [^String s]
        (let [sb (StringBuilder. s)]
          (.replace sb 2 3 "x")
          (str sb)))
#'user/replace-builder

user> (defn replace-vec [^String s]
        (clojure.string/join (assoc (vec s) 2 \x)))
#'user/replace-vec

user> (defn replace-subs [^String s]
        (str (subs s 0 2) "x" (subs s 3)))
#'user/replace-subs

user> (time (dotimes [_ 1000000] (replace-builder "123456789")))
"Elapsed time: 78.457028 msecs"
nil

user> (time (dotimes [_ 1000000] (replace-vec "123456789")))
"Elapsed time: 917.656951 msecs"
nil

user> (time (dotimes [_ 1000000] (replace-subs "123456789")))
"Elapsed time: 224.585971 msecs"
nil
like image 129
leetwinski Avatar answered May 30 '23 09:05

leetwinski