在clojure中,如何编写应用多个字符串替换的函数?
我想编写一个函数在clojure中,如何编写应用多个字符串替换的函数?,clojure,Clojure,我想编写一个函数replace multive,它接收一个字符串和一组替换,并应用所有替换(替换可以看到以前替换的结果) 我考虑了以下界面: (replace-several "abc" #"a" "c" #"b" "l" #"c" "j"); should return "jlj" 两个问题: 它是clojure中最惯用的界面吗 如何实现这个功能 备注:要进行单个替换,在中有可用的replace,
replace multive
,它接收一个字符串和一组替换,并应用所有替换(替换可以看到以前替换的结果)
我考虑了以下界面:
(replace-several "abc" #"a" "c"
#"b" "l"
#"c" "j"); should return "jlj"
两个问题:
备注:要进行单个替换,在中有可用的
replace
,因此您有replace
、reduce
和分区
。从这些构建块中,您可以构建您的替换几个第一次猜测
(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"
使用replace
、reduce
和partition
实现@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"
这里是另一个快照,但是它的输出结果不同,这一个使用了正则表达式引擎功能,因此可能更快,而且界面也不同,因为它将键映射到替换字符串。我提供这个,以防它可能对有类似问题的人有用
(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”您可以使用reduce和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")
我来晚了,但无论如何,我认为最惯用的方法是使用线程和多个替换:
(require '[clojure.string :refer [replace])
(-> "abc"
(replace #"a" "c")
(replace #"b" "l")
(replace #"c" "j"))
;=> "jlj"
这一点的含义非常清楚,尽管避免多次键入“replace”很好。我个人不会为此创建单独的函数,因为它只是现有Clojure函数的组合:
(reduce kv clojure.string/replace“Hello”{#“[A-Z]”“J”、“o”“y”}
;=>“果冻”
当然,如果您想要varargs和接口,那么:
是的,它看起来相当地道
我将这样实施它:
(defn替换许多[string&{:as rplcmnts}]
(减少kv clojure.string/replace string rplcmnts))
Docs刚刚注意到你可以将val
参数传递给reduce函数,如果不是因为你的评论,我永远不会意识到!看到我对kotarak的回复中的评论,我不知道你可以将val
参数传递给reduce
来累积结果,这与我的答案几乎相同。唯一的区别是e是在reduce中,我用了应用而不是解构。你的意思是(替换几个“abc”…
?@Josh我不理解你的问题我是说我认为“abd”
中的“d”是一个打字错误,对吗?当然应该是“abc”
,或者您描述的替换多个
功能会很奇怪。谢谢@Josh。您完全正确。事实上,我在回答中答对了:)谢谢这一块金子。我完全错过了escape
。非常好。我会把它添加到箭袋中。谢谢你的这段代码,正是我想要的。我还不太理解你的代码,但我尝试过:(替换地图“这是一个检查它是否按预期工作的测试”{“这是”“htis si”“检查是否”“hceck fi”“按预期运行”“任意”})
而且它工作得很好!如果您想知道它是如何工作的,我正在创建一个由映射键组成的正则表达式。clojure.string/replace
将使用该正则表达式并将匹配项传递给m
,该函数起到函数的作用。因为m
已经是要替换的映射,它将返回正确的替换.
(str/escape "abc" {\a "c" \b "l" \c "j"})
; => "clj"