在clojure中,如何编写一个应用多个字符串替换的函数?

时间:2012-03-05 14:11:37

标签: clojure

我想编写一个函数replace-several,它接收一个字符串和一组替换并应用所有替换(替换部分会看到之前替换的结果)。

我想到了以下界面:

(replace-several "abc" #"a" "c" 
                       #"b" "l"
                       #"c" "j"); should return "jlj" 

两个问题:

  1. 它是clojure中最惯用的界面吗?
  2. 如何实现此功能?
  3. 备注:要进行一次替换,clojure.string中有replace个可用。

8 个答案:

答案 0 :(得分:12)

使用replacereducepartition实施@ kotarak的建议:

(defn replace-several [content & replacements]
      (let [replacement-list (partition 2 replacements)]
        (reduce #(apply string/replace %1 %2) content replacement-list)))
; => (replace-several "abc" #"a" "c" #"b" "l" #"c" "j")
  "jlj"

答案 1 :(得分:9)

所以你有replacereducepartition。从这些构建基块中,您可以构建replace-several

答案 2 :(得分:4)

这是另一个镜头但不同的输出结果,这个使用正则表达式引擎功能,因此它可能更快,界面也不同,因为它将键映射到替换字符串。我提供这个,以防有问题的人可能会有用。

(defn replace-map
  "given an input string and a hash-map, returns a new string with all
  keys in map found in input replaced with the value of the key"
  [s m]
  (clojure.string/replace s
              (re-pattern (apply str (interpose "|" (map #(java.util.regex.Pattern/quote %) (keys m)))))
          m))

所以用法就是这样:

 (replace-map "abc" {"a" "c" "b" "l" "c" "j"})

=> “CLJ”

答案 3 :(得分:4)

我迟到了这个派对,但是为了它的价值,我认为大多数惯用的方法是使用线程和多个替换:

(require '[clojure.string :refer [replace])

(-> "abc"
    (replace #"a" "c")
    (replace #"b" "l")
    (replace #"c" "j"))

;=> "jlj"

这一点的含义非常清楚,但避免多次输入“替换”是很好的。

答案 4 :(得分:1)

你可以使用reduce with replace:

(defn replace-several
  [str & replacements]
  (reduce (fn [s [a b]]
            (clojure.string/replace s a b))
          str
          (partition 2 replacements)))

(replace-several "abc"
                 #"a" "c"
                 #"b" "l"
                 #"c" "j")

答案 5 :(得分:1)

(str/escape "abc" {\a "c" \b "l" \c "j"})

; => "clj"

文档escape

答案 6 :(得分:0)

首先猜测..

(defn replace-several [string & mappings]
  (loop [grouped-mappings (partition 2 mappings) string string]
    (if (empty? grouped-mappings)
      string
      (let [[re rep] (first grouped-mappings)]
        (recur (rest grouped-mappings) (clojure.string/replace string re rep))))))
; => (replace-several "abc" #"a" "c" #"b" "l" #"c" "j")
  "jlj"

答案 7 :(得分:0)

就我个人而言,我不会为此创建单独的函数,因为它只是现有Clojure函数的组合:

(reduce-kv clojure.string/replace "Hello" {#"[A-Z]" "J", "o" "y"} ;=> "Jelly"

当然,如果你想要varargs和界面,那么:

  1. 是的,似乎是合理的惯用语
  2. 我实施它:
  3. (defn replace-many [string & {:as rplcmnts}] (reduce-kv clojure.string/replace string rplcmnts))