Reputation: 151
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.
Upvotes: 4
Views: 858
Reputation: 17859
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
Upvotes: 6
Reputation: 8854
Piotr is right, but here's another way to do it. It's not really shorter, but I think it's slightly easier to understand.
(clojure.string/join (assoc (vec "abc") 1 \B)) ;=> "aBc"
(clojure.string/join (assoc (vec "abc") 1 "B")) ;=> "aBc"
You can also use apply str
or reduce str
instead of join
.
Clojure strings are treated like vectors when passed to get
:
(get "abc" 1) ;=> \b
However, they don't seem to be treated as vectors in any other context. This won't work:
(assoc "abc" 1 \B)
ClassCastException java.lang.String cannot be cast to clojure.lang.Associative ...
(For the record, clojure.string/replace
and clojure.string/replace-first
will search for a matching substring and replace it, but that's not what you asked about.)
Upvotes: 2
Reputation: 13175
Unfortunately, there is no such function in Clojure API. Even java.lang.String
doesn't have such method. You need to implement it by yourself.
Upvotes: 3