我想修改一个字符串,通过对它的一些字符应用一个函数(通过开始索引和长度)。
例如,我想将字符串"aaaaa"
的ascii表示从第二个索引增加到第四个。如何在Clojure中通过索引修改字符串?
[start=1 length=3]
"aaaaa" => "abbba"
我能想到的是运用map
的唯一方法,但它越过所有的序列。
我想修改一个字符串,通过对它的一些字符应用一个函数(通过开始索引和长度)。
例如,我想将字符串"aaaaa"
的ascii表示从第二个索引增加到第四个。如何在Clojure中通过索引修改字符串?
[start=1 length=3]
"aaaaa" => "abbba"
我能想到的是运用map
的唯一方法,但它越过所有的序列。
您可以使用subs
获取您不想修改的部分。改性用str
后一起串连结果:
(defn replace-in-str [f in from len]
(let [before (subs in 0 from)
after (subs in (+ from len))
being-replaced (subs in from (+ from len))
replaced (f being-replaced)]
(str before replaced after)))
你可以称它为:
(replace-in-str
(fn [sub-str] (apply str (map #(char (+ 1 (int %))) sub-str)))
"aaaaa"
1
3)
我想用map-index
只在指定的索引执行操作的:
((fn [op start length] (map-indexed (fn [i m] (if (<= start i length)
(op m)
m)) "aaaaa"))
#(char (+ 1 (int %)))
1
3)
=> (\a \b \b \b \a)
你可以用'(apply str)'来包装最终结果,将它变成一个String btw。 – Carcigenicate
确实map
将该函数应用于序列中的每个元素。一种解决方法是从map-indexed
开始。与map
不同,map-indexed
将元素索引作为第一个参数传递给映射函数。当我们有元素的索引时,我们可以使用它来选择是否需要执行操作或仅按原样返回元素。
一个解决方案可能是这样的:
(defn inc-char [c]
(char (inc (long c))))
(defn if-in-range [from to f]
(fn [i x & args]
(if (<= from i (dec to))
(apply f x args)
x)))
(defn map-subs [from to f s]
(apply str (map-indexed (if-in-range from to f) s)))
(map-subs 1 4 inc-char "aaaaa")
;; "abbba"
是的,这也是我想到的,虽然我会认为clojure有内置的东西来处理... – itaied
在这里你去:
(defn replace-str
[s start-i end-i]
(apply str (map-indexed (fn [index val]
(if (and (>= index start-i)
(<= index end-i))
(char (+ (int val) 1))
val))
s)))
(replace-str "aaaa" 1 2)
;=> "abba"
是啊,我虽然做的,但它听起来像一个可怕的大量的工作,你觉得什么我的方案? (在我的答案中有所描述) – itaied
即使没有进行字符串替换,我也无法使用map-indexed,在这种情况下,我会使用'subvec'。 –
是的,它是明确的更换,但如何应用功能? – itaied