首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >清理格式不正确的电话号码

清理格式不正确的电话号码
EN

Code Review用户
提问于 2022-12-15 21:27:00
回答 1查看 94关注 0票数 2

这是这里的运动主义的一个问题,目标是清理格式糟糕的电话号码。这些规则是:

  • 如果电话号码小于10位数,则假定它是一个错误的号码。
  • 如果电话号码是10位,假设它是好的。
  • 如果电话号码是11位数,第一个号码是1,请修剪1并使用前10位数字。
  • 如果电话号码是11位,而第一个号码不是1,那么它就是一个坏号码。
  • 如果电话号码超过11位数,则假定它是一个错误的号码。

一个函数应该以pretty-print形式(123) 456-7890表示数字。

这是我的解决办法。我对Clojure非常陌生,我确信它在某些方面不是惯用的。例如,我是否应该将数字的不同部分作为单独的变量存储?

我还会对如何格式化代码以使其更容易阅读的技巧感兴趣,我只知道lispy多行,我发现它有点太激进了。

所有反馈非常感谢。

代码语言:javascript
复制
(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)))))
EN

回答 1

Code Review用户

回答已采纳

发布于 2022-12-18 14:19:45

我建议您查看Clojure Cheatsheet并熟悉专门用于处理字符串的函数。还有一个库clojure.string,包含更多的库。有了这些函数,您就不必将字符串转换为序列,然后重复返回。

例如,您的pretty-print- subs返回字符串,concat返回序列,apply str再次返回字符串。在开始时选择正确的数据结构,使用专用函数并尽可能少地进行转换。

使用:requirens中包含clojure.string库:

代码语言:javascript
复制
(ns phone-number
  (:require [clojure.string :as s])
  (:gen-class))

我将从area-code开始。这个函数可以用->> (线程-最后宏)和clojure.string/join来改进,如下所示:

代码语言:javascript
复制
(defn area-code [num-string]
  (->> (number num-string)
       (take 3)
       s/join))

但是您也可以使用subs

代码语言:javascript
复制
(defn area-code [num-string]
  (subs (number num-string) 0 3))

下一个,pretty-print。您可以在这里使用format

代码语言:javascript
复制
(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。通常使用这些元素创建一个集合并在参数上调用它,如下所示:

代码语言:javascript
复制
(defn digit-not-one-or-zero [digit]
  (not (#{\0 \1} digit)))

甚至更短:

代码语言:javascript
复制
(def digit-not-one-or-zero (complement #{\0 \1}))

您的clean-number是可以的(我只需要在末尾添加s/join以确保它将像这里的任何其他函数一样返回一个字符串),除非您想要使用一些regex:

代码语言:javascript
复制
(defn clean-number [num-string]
  (s/replace num-string #"\D" ""))

接下来是numbercheck-valid

  • 不要使用嵌套的ifs-学习condcondpcase并使用这些。When在这里也很有用。
  • 不要使用(if ... true false)。在Clojure中,所有值在逻辑上都是正确的或错误的。唯一的“假”值是falsenil --所有其他值在逻辑上都是正确的。以这个例子为例:
代码语言:javascript
复制
(if (and (digit-not-one-or-zero (first clean-string))
         (digit-not-one-or-zero (nth clean-string 3)))
  true
  false)

你只需写:

代码语言:javascript
复制
(and (digit-not-one-or-zero (first clean-string))
     (digit-not-one-or-zero (nth clean-string 3)))
  • check-valid太长了--你应该把它分解成更小的函数。

所以,这是我的版本,你可以学习。注意使用简短的函数、习惯用法和适当的流控制宏是如何提高可读性的:

代码语言:javascript
复制
(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" ""))
代码语言:javascript
复制
(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))))
代码语言:javascript
复制
(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的替代解决方案:

代码语言:javascript
复制
(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"))
票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/281972

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档