e.g。我想用字符“X”替换字符串“123456789”中索引2处的字符。我知道我可以做(str (subs "123456789" 0 2) "X" (subs "123456789" 3))
之类的事情,但我想知道是否已有内置的库函数。
答案 0 :(得分:6)
另一种方式,是使用java StringBuilder
,它具有这个确切的api,并且可能比subs
或vec
更快(并且显然更快)你一次做了很多改变):
user> (let [sb (StringBuilder. "123456789")]
(str (.replace sb 1 2 "x")))
"1x3456789"
多项更改:
user> (let [sb (StringBuilder. "123456789")]
(doseq [idx [1 3 5]]
(.replace sb idx (inc idx) "x"))
(str sb))
"1x3x5x789"
一点性能基准:
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
答案 1 :(得分:3)
不幸的是,Clojure API中没有这样的功能。即使java.lang.String
也没有这样的方法。你需要自己实现它。
答案 2 :(得分:2)
Piotr是对的,但这是另一种方式。它不是很短,但我认为它更容易理解。
(clojure.string/join (assoc (vec "abc") 1 \B)) ;=> "aBc"
(clojure.string/join (assoc (vec "abc") 1 "B")) ;=> "aBc"
您也可以使用apply str
或reduce str
代替join
。
传递给get
时,Clojure字符串被视为向量:
(get "abc" 1) ;=> \b
然而,它们似乎在任何其他情况下都不被视为载体。这不会起作用:
(assoc "abc" 1 \B)
ClassCastException java.lang.String cannot be cast to clojure.lang.Associative ...
(对于记录,clojure.string/replace
和clojure.string/replace-first
会搜索匹配的子字符串并替换它,但这不是您询问的内容。)