2017-05-28 59 views
1

我想修改一个字符串,通过对它的一些字符应用一个函数(通过开始索引和长度)。
例如,我想将字符串"aaaaa"的ascii表示从第二个索引增加到第四个。如何在Clojure中通过索引修改字符串?

[start=1 length=3] 
"aaaaa" => "abbba" 

我能想到的是运用map的唯一方法,但它越过所有的序列。

回答

2

您可以使用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) 
+0

是啊,我虽然做的,但它听起来像一个可怕的大量的工作,你觉得什么我的方案? (在我的答案中有所描述) – itaied

+0

即使没有进行字符串替换,我也无法使用map-indexed,在这种情况下,我会使用'subvec'。 –

+0

是的,它是明确的更换,但如何应用功能? – itaied

0

我想用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) 
+1

你可以用'(apply str)'来包装最终结果,将它变成一个String btw。 – Carcigenicate

1

确实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" 
+0

是的,这也是我想到的,虽然我会认为clojure有内置的东西来处理... – itaied

0

在这里你去:

(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"