如何在 Clojure 中创建 "replace-second" 函数?
How to create a "replace-second" function in Clojure?
(clojure.string/replace-first "a x x c d" #"x" "b" )) ; Replace first
如果我想替换上面字符串中的第二个 x 怎么办?
例如它可能是:
(let [n #{1}
s "a x x x x c d"
re #"x"
m (re-find re s)
xs (s/split s re)
vs (conj (vec (take (dec (count xs)) (repeat m))) nil)
replacement ".."]
(apply str (interleave xs (map-indexed (fn [index v] (if (n index) replacement v)) vs))))
一个Matcher instance lets us iterate over the matches:
(defn replace-nth [input pattern n new-value]
(let [m (re-matcher pattern input)]
(loop [counter n]
(if (.find m)
(if (= counter 0)
(str (subs input 0 (.start m))
new-value
(subs input (.end m)))
(recur (dec counter)))
input))))
(replace-nth "a x x c d" #"x" 1 "Mjao!")
;; => "a x Mjao! c d"
嗯,也许你可以妥协?
(-> "a x x c d"
(clojure.string/replace-first #"x" "_")
(clojure.string/replace-first #"x" "b" )
(clojure.string/replace-first #"_" "x"))
只要确保 _
不能在字符串中即可。
:)
好的,再来一个(模块化的):
首先,要替换的范围的惰性序列:
(defn ranges [re s]
(let [m (re-matcher re s)]
(for [_ (range) :while (re-find m)]
[(.start m) (.end m)])))
user> (ranges #"x" "a x x b x")
;;=> ([2 3] [4 5] [8 9])
然后范围替换函数:
(defn replace-range [[a b] repl s]
(str (subs s 0 a) repl (subs s b)))
user> (replace-range [1 3] "REPLACED" "a b c d e f")
;;=> "aREPLACED c d e f"
然后你做任何你想做的事:
(let [s "a x x b x"]
(map #(replace-range % "ZEE" s)
(ranges #"x" s)))
;;=> ("a ZEE x b x" "a x ZEE b x" "a x x b ZEE")
或
(let [s "a x x b x"]
(-> (ranges #"x" s)
second
(replace-range "REPLACED" s)))
;;=> "a x REPLACED b x"
(clojure.string/replace-first "a x x c d" #"x" "b" )) ; Replace first
如果我想替换上面字符串中的第二个 x 怎么办?
例如它可能是:
(let [n #{1}
s "a x x x x c d"
re #"x"
m (re-find re s)
xs (s/split s re)
vs (conj (vec (take (dec (count xs)) (repeat m))) nil)
replacement ".."]
(apply str (interleave xs (map-indexed (fn [index v] (if (n index) replacement v)) vs))))
一个Matcher instance lets us iterate over the matches:
(defn replace-nth [input pattern n new-value]
(let [m (re-matcher pattern input)]
(loop [counter n]
(if (.find m)
(if (= counter 0)
(str (subs input 0 (.start m))
new-value
(subs input (.end m)))
(recur (dec counter)))
input))))
(replace-nth "a x x c d" #"x" 1 "Mjao!")
;; => "a x Mjao! c d"
嗯,也许你可以妥协?
(-> "a x x c d"
(clojure.string/replace-first #"x" "_")
(clojure.string/replace-first #"x" "b" )
(clojure.string/replace-first #"_" "x"))
只要确保 _
不能在字符串中即可。
:)
好的,再来一个(模块化的):
首先,要替换的范围的惰性序列:
(defn ranges [re s]
(let [m (re-matcher re s)]
(for [_ (range) :while (re-find m)]
[(.start m) (.end m)])))
user> (ranges #"x" "a x x b x")
;;=> ([2 3] [4 5] [8 9])
然后范围替换函数:
(defn replace-range [[a b] repl s]
(str (subs s 0 a) repl (subs s b)))
user> (replace-range [1 3] "REPLACED" "a b c d e f")
;;=> "aREPLACED c d e f"
然后你做任何你想做的事:
(let [s "a x x b x"]
(map #(replace-range % "ZEE" s)
(ranges #"x" s)))
;;=> ("a ZEE x b x" "a x ZEE b x" "a x x b ZEE")
或
(let [s "a x x b x"]
(-> (ranges #"x" s)
second
(replace-range "REPLACED" s)))
;;=> "a x REPLACED b x"