Clojure中是否有内置函数来替换字符串中特定索引处的字符?

时间:2016-04-21 13:31:29

标签: clojure

e.g。我想用字符“X”替换字符串“123456789”中索引2处的字符。我知道我可以做(str (subs "123456789" 0 2) "X" (subs "123456789" 3))之类的事情,但我想知道是否已有内置的库函数。

3 个答案:

答案 0 :(得分:6)

另一种方式,是使用java StringBuilder,它具有这个确切的api,并且可能比subsvec更快(并且显然更快)你一次做了很多改变):

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 strreduce 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/replaceclojure.string/replace-first会搜索匹配的子字符串并替换它,但这不是您询问的内容。)