这是这里的运动主义的一个问题,目标是清理格式糟糕的电话号码。这些规则是:
一个函数应该以pretty-print形式(123) 456-7890表示数字。
这是我的解决办法。我对Clojure非常陌生,我确信它在某些方面不是惯用的。例如,我是否应该将数字的不同部分作为单独的变量存储?
我还会对如何格式化代码以使其更容易阅读的技巧感兴趣,我只知道lispy多行,我发现它有点太激进了。
所有反馈非常感谢。
(ns phone-number)
(defn digit-not-one-or-zero [digit]
(and (not (= \0 digit))
(not (= \1 digit))))
(defn clean-number [num-string]
;; strip all non-digit characters from a string
(filter #(Character/isDigit %) num-string))
(defn check-valid [num-string]
;; number is valid only if:
;; a) length is between 10-11 chars
;; b) if 11 chars, first digit must be 1
;; c) (after stripping first digit if 11), first and fourth can't be 0 or 1
(let [clean-string (clean-number num-string)
len (count clean-string)]
(if (or (< len 10) (> len 11))
false
(if (= len 11)
(if (= \1 (first clean-string))
(check-valid (rest clean-string))
false)
(if (and (digit-not-one-or-zero (first clean-string))
(digit-not-one-or-zero (nth clean-string 3)))
true
false)))))
(defn number [num-string]
(if (check-valid num-string)
(let [clean-string (clean-number num-string)]
(if (= (count clean-string) 10)
(apply str (clean-number clean-string)) (apply str (rest (clean-number clean-string)))))
"0000000000"))
(defn area-code [num-string]
;; get the first 3 chars of the cleaned up number
(apply str (take 3 (number num-string))))
(defn pretty-print [num-string]
(let [formatted-number (number num-string)]
(apply str (concat
"(" (area-code num-string) ")" " " (subs formatted-number 3 6) "-" (subs formatted-number 6)))))发布于 2022-12-18 14:19:45
我建议您查看Clojure Cheatsheet并熟悉专门用于处理字符串的函数。还有一个库clojure.string,包含更多的库。有了这些函数,您就不必将字符串转换为序列,然后重复返回。
例如,您的pretty-print- subs返回字符串,concat返回序列,apply str再次返回字符串。在开始时选择正确的数据结构,使用专用函数并尽可能少地进行转换。
使用:require在ns中包含clojure.string库:
(ns phone-number
(:require [clojure.string :as s])
(:gen-class))我将从area-code开始。这个函数可以用->> (线程-最后宏)和clojure.string/join来改进,如下所示:
(defn area-code [num-string]
(->> (number num-string)
(take 3)
s/join))但是您也可以使用subs:
(defn area-code [num-string]
(subs (number num-string) 0 3))下一个,pretty-print。您可以在这里使用format:
(defn pretty-print [num-string]
(let [validated (number num-string)]
(format "(%s) %s-%s" (area-code validated)
(subs validated 3 6)
(subs validated 6))))下一个,digit-not-one-or-zero。通常使用这些元素创建一个集合并在参数上调用它,如下所示:
(defn digit-not-one-or-zero [digit]
(not (#{\0 \1} digit)))甚至更短:
(def digit-not-one-or-zero (complement #{\0 \1}))您的clean-number是可以的(我只需要在末尾添加s/join以确保它将像这里的任何其他函数一样返回一个字符串),除非您想要使用一些regex:
(defn clean-number [num-string]
(s/replace num-string #"\D" ""))接下来是number和check-valid。
ifs-学习cond、condp和case并使用这些。When在这里也很有用。(if ... true false)。在Clojure中,所有值在逻辑上都是正确的或错误的。唯一的“假”值是false和nil --所有其他值在逻辑上都是正确的。以这个例子为例:(if (and (digit-not-one-or-zero (first clean-string))
(digit-not-one-or-zero (nth clean-string 3)))
true
false)你只需写:
(and (digit-not-one-or-zero (first clean-string))
(digit-not-one-or-zero (nth clean-string 3)))check-valid太长了--你应该把它分解成更小的函数。所以,这是我的版本,你可以学习。注意使用简短的函数、习惯用法和适当的流控制宏是如何提高可读性的:
(ns phone-number
(:require [clojure.string :as s])
(:gen-class))
(def allowed-digits (complement #{\0 \1}))
(defn clean-number [num-string]
(s/replace num-string #"\D" ""))(defn validate10 [s]
(and (allowed-digits (.charAt s 0))
(allowed-digits (.charAt s 3))
s))
(defn validate11 [s]
(when (= \1 (.charAt s 0))
(validate10 (subs s 1))))(defn validate [num-string]
(condp = (count num-string)
11 (validate11 num-string)
10 (validate10 num-string)
false))
(defn number [num-string]
(if-let [valid (validate (clean-number num-string))]
valid
"0000000000"))
(defn area-code [num-string]
(subs (number num-string) 0 3))
(defn pretty-print [num-string]
(let [validated (number num-string)]
(format "(%s) %s-%s" (area-code validated)
(subs validated 3 6)
(subs validated 6))))编辑:使用regexes的替代解决方案:
(defn number [num-string]
(if-let [valid (->> (s/replace num-string #"\D" "")
(re-matches #"1?([^01]..[^01].{6})")
second)]
valid
"0000000000"))
(defn area-code [num-string]
(subs (number num-string) 0 3))
(defn pretty-print [num-string]
(s/replace (number num-string)
#"(\d{3})(\d{3})(\d{4})"
"($1) $2-$3"))https://codereview.stackexchange.com/questions/281972
复制相似问题