我有不同的字符串,像“45”和“45px”。如何将这两个字符串转换为数字45?
(number? 0.5)
;;=> true
因此,上述十进制数也应该被解析。
现在或许并没有直接回答这个问题,但是对于一般用途,我认为你应该严格区分它是否为数字(所以不允许使用“px”),并让调用者通过返回 nil 来处理非数字:
(defn str->number [x]
(when-let [num (re-matches #"-?\d+\.?\d*" x)]
(try
(Float/parseFloat num)
(catch Exception _
nil))))
如果浮点数在您的领域中存在问题,可以将Float/parseFloat
替换为bigdec
或其他内容。
尝试使用以下方法来避免在某些字符串上出现异常:
(defn string-to-number [in]
(let [s (strip-whitespace in) ;; trim
f (re-find #"\d+" s)] ;; search digit else nil
(if f (Integer/parseInt f) 0))) ;; if not-nil do cast
(string-to-number "-")
(string-to-number "10")
(string-to-number "px10")
(string-to-number "1200 xr")
对于简单的情况,您可以像上面提到的那样使用正则表达式来提取第一个数字字符串。
如果您遇到更复杂的情况,可以使用InstaParse库:
(ns tst.parse.demo
(:use tupelo.test)
(:require
[clojure.string :as str]
[instaparse.core :as insta]
[tupelo.core :as t] ))
(t/refer-tupelo)
(dotest
(let [abnf-src "
size-val = int / int-px
int = digits ; ex '123'
int-px = digits <'px'> ; ex '123px'
<digits> = 1*digit ; 1 or more digits
<digit> = %x30-39 ; 0-9
"
tx-map {:int (fn fn-int [& args]
[:int (Integer/parseInt (str/join args))])
:int-px (fn fn-int-px [& args]
[:int-px (Integer/parseInt (str/join args))])
:size-val identity
}
parser (insta/parser abnf-src :input-format :abnf)
instaparse-failure? (fn [arg] (= (class arg) instaparse.gll.Failure))
parse-and-transform (fn [text]
(let [result (insta/transform tx-map
(parser text))]
(if (instaparse-failure? result)
(throw (IllegalArgumentException. (str result)))
result))) ]
(is= [:int 123] (parse-and-transform "123"))
(is= [:int-px 123] (parse-and-transform "123px"))
(throws? (parse-and-transform "123xyz"))))
(t/refer-tupelo)
而不是让用户执行(:require [tupelo.core :refer :all])
呢? - Qwerp-Derp
"9"
转换为9
的人,这是我使用过最好的方法:(Integer. "9")
。 - Dennis Hackethal