(defn num-as-words [n]
(let [words '("zero" "one" "two" "three" "four"
"five" "six" "seven" "eight" "nine")]
(clojure.string/join "-"
(map (fn [x] (nth words (Integer. (re-find #"d" (str x)) ))) (str n)))))
我已经编写了一个名为num as words的函数,它接受一个整数并将其显示为完整的单词,例如,如果您输入(123),它将返回(一二三)。
我用地图做过,但我想知道是否还有其他方法?我还想知道是否有另一种方式来连接单词,而不是clojure.string_join,我最初使用interpose,但不喜欢它的输出方式,因为它看起来像("一"-"二"-"三")。
如有任何帮助,我们将不胜感激,谢谢。
user=> (clojure.pprint/cl-format ; formatted printing
nil ; ... to a string
"~{~R~^-~}" ; format (see below)
(map ; map over characters
(fn [x] (Integer. (str x))) ; convert char to integer
(str 123))) ; convert number to string
"one-two-three"
首先,我们取输入数字,在本例中硬编码为
"123"
,将其强制为字符串,并通过map
迭代生成的字符串的字符。对于每个字符,我们构建一个包含该字符的字符串,并将其解析为Integer
。因此,我们获得了一个数字列表。更确切地说,
(fn [x] ...)
是一个接受一个参数的函数。您可能应该将其命名为char
(抱歉),因为我们对字符进行迭代。当我们评估(str x)
时,我们得到一个包含一个字符的字符串,即x
。例如,如果字符为2
,则生成的字符串为"2"
。(Integer. string)
表单(注意点!)调用Integer
类的构造函数,该类将字符串解析为整数。继续我们的例子,(Integer. "2")
将产生整数2。我们使用
cl-format
将数字列表打印到一个新字符串中(根据false
参数的请求)。为了做到这一点,我们指定如下格式:~{...~}
对列表进行迭代,并在每个元素的大括号内执行格式。~R
将数字打印为英文单词(1=>一等)- 当没有剩余的参数时,
~^
将跳过~{...~}
进行的迭代。因此,当我们打印最后一个数字时,~^
后面的部分不会打印 - 在
~^
之后的仅仅是字符-
。这是用来分隔字符串的,但我们必须注意不要在循环的所有迭代中都打印破折号,否则生成的字符串将以破折号结束
如果任何字符无法解析为Integer,则函数将报告错误。在将输入转换为字符串之前,您可能需要先检查输入是否真的是正整数。
我会这样实现它:
(defn num-as-words [n]
(let [words ["zero" "one" "two" "three" "four" "five" "six" "seven" "eight" "nine"]]
(->> (str n)
(map #(Character/getNumericValue %))
(map words)
(clojure.string/join "-"))))
- 使用vector将简化实现
- 您可以将数字字符串视为序列,而不是使用正则表达式拆分数字字符串。在这种情况下,应该使用
Charactor/getNumericValue
将char转换为integer - 可以使用
->>
宏 - 使用
clojure.string/join
看起来不错 interpose
返回惰性序列。这就是为什么它像("one" "-" "two"...)
一样返回。您应该将apply str
转换为结果,将(apply str (interpose ...))
转换为字符串
如果你想处理负数,你可以这样修改代码:
(defn num-as-words [n]
(if (< n 0)
(str "-" (num-as-words (- n)))
(let [words ["zero" "one" "two" "three" "four" "five" "six" "seven" "eight" "nine"]]
(->> (str n)
(map #(Character/getNumericValue %))
(map words)
(clojure.string/join "-")))))
这将在前面为-
做准备。如果你只是想抛出一个错误,你可以使用前提条件:
(defn num-as-words [n]
{:pre [(<= 0 n)]}
(let [words ["zero" "one" "two" "three" "four" "five" "six" "seven" "eight" "nine"]]
...
当接收到负数时,这将抛出AssertionError
。