我是Clojure的新手,我正在从labrepl做一些基本的东西,现在我想编写一个用其他字母替换某些字母的函数,例如:elosska→elößkä。
我写了这个:
(ns student.dialect (:require [clojure.string :as str]))
(defn germanize
[sentence]
(def german-letters {"a" "ä" "u" "ü" "o" "ö" "ss" "ß"})
(doseq [[original-letter new-letter] german-letters]
(str/replace sentence original-letter new-letter)))
但它没有像我期望的那样起作用。你能帮帮我吗?
答案 0 :(得分:16)
这是我的看法,
(def german-letters {"a" "ä" "u" "ü" "o" "ö" "ss" "ß"})
(defn germanize [s]
(reduce (fn[sentence [match replacement]]
(str/replace sentence match replacement)) s german-letters))
(germanize "elosska")
答案 1 :(得分:6)
这里有两个问题:
doseq
不会保留由其评估创建的列表头部,因此您不会获得任何结果str/replace
处理单独的文本副本,产生4种不同的结果 - 您可以将doseq
替换为for
来检查这一点,然后您将获得包含4个条目的列表。您可以按照以下方式重写代码:
(def german-letters {"a" "ä" "u" "ü" "o" "ö" "ss" "ß"})
(defn germanize [sentence]
(loop [text sentence
letters german-letters]
(if (empty? letters)
text
(let [[original-letter new-letter] (first letters)]
(recur (str/replace text original-letter new-letter)
(rest letters))))))
在这种情况下,会收集中间结果,因此所有替换都应用于相同的字符串,从而生成正确的字符串:
user> (germanize "elosska")
"elößkä"
P.S。也不建议在函数中使用def
- 最好将它用于顶级表单
答案 2 :(得分:6)
亚历克斯当然已经使用doseq
正确回答了有关原始问题的问题......但我发现这个问题很有意思,并希望看到更具“功能性”的解决方案。我的意思是不使用循环。
我想出了这个:
(ns student.dialect (:require [clojure.string :as str]))
(defn germanize [sentence]
(let [letters {"a" "ä" "u" "ü" "o" "ö" "ss" "ß"}
regex (re-pattern (apply str (interpose \| (keys letters))))]
(str/replace sentence regex letters)))
产生相同的结果:
student.dialect=> (germanize "elosska")
"elößkä"
regex (re-pattern...
行简单地评估为#"ss|a|o|u"
,如果作为显式字符串输入,它本来更清晰,更易于阅读,但我认为最好只有一个德语定义字母。