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

Clojure中是否有内置函数来替换字符串中特定索引处的字符?,clojure,Clojure,e、 g.我想用字符“X”替换字符串“123456789”中索引2处的字符。我知道我可以做一些类似于(str(subs“123456789”02)“X”(subs“123456789”3))的事情,但我想知道是否已经有一个用于此的内置库函数。不幸的是,Clojure API中没有这样的函数。甚至java.lang.String也没有这样的方法。你需要自己去实现它 Piotr是对的,但这里有另一种方法。它不是很短,但我认为它更容易理解 (clojure.string/join (assoc (ve

e、 g.我想用字符“X”替换字符串“123456789”中索引2处的字符。我知道我可以做一些类似于
(str(subs“123456789”02)“X”(subs“123456789”3))
的事情,但我想知道是否已经有一个用于此的内置库函数。

不幸的是,Clojure API中没有这样的函数。甚至
java.lang.String
也没有这样的方法。你需要自己去实现它

Piotr是对的,但这里有另一种方法。它不是很短,但我认为它更容易理解

(clojure.string/join (assoc (vec "abc") 1 \B))  ;=> "aBc"
(clojure.string/join (assoc (vec "abc") 1 "B")) ;=> "aBc"
您也可以使用
apply str
reduce str
代替
join

Clojure字符串在传递到
get
时被视为向量:

(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
将搜索匹配的子字符串并将其替换,但这不是您所要求的。)

另一种方法是使用java的
StringBuilder
,它有这个精确的api,并且可能更快,比
subs
vec
更快(如果您同时进行大量更改,则速度明显更快):

多项更改:

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

我通常不喜欢过早的性能参数,但在性能方面使用
vec
对我来说似乎是不合理的(根据我刚刚运行的一些基于标准的基准测试,速度慢了一个数量级)。在我看来,在这种情况下,一个合适的函数名就足以实现明确性。
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