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

时间:2017-01-03 16:17:43

标签: 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但不喜欢它输出的方式,因为它看起来像("一个&# 34;" - "" 2"" - "" 3")。

非常感谢任何帮助,谢谢。

2 个答案:

答案 0 :(得分:5)

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)时,我们获得一个包含一个char的字符串,即x。例如,如果字符为\2,则生成的字符串为"2"(Integer. string)形式(注意点!)调用Integer类的构造函数,该类将字符串解析为整数。要继续我们的示例,(Integer. "2")将产生整数2。

  • 我们使用cl-format将数字列表打印成一个新字符串(由false参数请求)。为此,我们指定格式如下:

  • ~{...~}遍历列表并在每个元素的大括号内执行格式。

  • ~R打印一个数字作为英文单词(1 => one等)
  • 当没有剩余参数时,
  • ~^转义~{...~}进行的迭代。因此,当我们打印最后一位数字时,不会打印~^后面的部分。
  • ~^后面的内容只是字符-。这用于分隔字符串,但我们必须注意不要为循环的所有迭代打印破折号,否则结果字符串将以破折号结束。

如果无法将任何字符解析为整数,则该函数将报告错误。在将输入转换为字符串之前,您可能需要首先检查输入是否为正整数。

答案 1 :(得分:3)

我会像这样实现它:

(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转换为整数。
  • 您可以使用->>宏。
  • 使用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