编写一个函数,在Clojure中用完整的单词打印(非负)整数


(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

最新更新