「45」、「45px」など、さまざまな文字列があります。これらの両方を45に変換する方法を教えてください。
"9"
してに変換しようとしている人にとって9
、これは私にとってうまくいった最高のものです(Integer. "9")
。
「45」、「45px」など、さまざまな文字列があります。これらの両方を45に変換する方法を教えてください。
"9"
してに変換しようとしている人にとって9
、これは私にとってうまくいった最高のものです(Integer. "9")
。
回答:
これは上で動作します10px
かpx10
(defn parse-int [s]
(Integer. (re-find #"\d+" s )))
最初の連続する数字のみを解析するので
user=> (parse-int "10not123")
10
user=> (parse-int "abc10def11")
10
Exception in thread "main" java.lang.ClassNotFoundException: Integer.,
私はsnrobotの答えが好きです。Javaメソッドを使用する方が、この単純な使用例でread-stringを使用するよりも簡単で堅牢です。私はいくつかの小さな変更を行いました。著者は負の数を除外しなかったので、負の数を許可するように調整しました。また、文字列の先頭から始まる数字を必要とするようにしました。
(defn parse-int [s]
(Integer/parseInt (re-find #"\A-?\d+" s)))
さらに、先行ゼロがある場合でも、基数が指定されていない場合、Integer / parseIntは10進数として解析されることがわかりました。
まず、整数のみを解析します(これはgoogleへのヒットであり、適切な背景情報であるため):
あなたはリーダーを使うことができます:
(read-string "9") ; => 9
読んだ後、それが数字であることを確認できます:
(defn str->int [str] (if (number? (read-string str))))
ユーザー入力がclojureリーダーによって信頼できるかどうかわからないので、読み取られる前に確認できます。
(defn str->int [str] (if (re-matches (re-pattern "\\d+") str) (read-string str)))
私は最後の解決策を好むと思います。
そして今、あなたの特定の質問に。次のように、整数で始まるものを解析するには29px
:
(read-string (second (re-matches (re-pattern "(\\d+).*") "29px"))) ; => 29
if
ので、あなたはa when
であるべきです。
read-string
それらを8進数として解釈します:(read-string "08")
例外をスローします。Integer/valueOf
:小数として扱い、それらを(Integer/valueOf "08")
8と評価する
read-string
空の文字列または「29px」のようなものを与えると例外がスローされることにも注意してください
(defn parse-int [s]
(Integer. (re-find #"[0-9]*" s)))
user> (parse-int "10px")
10
user> (parse-int "10")
10
Integer/valueOf
、通常はIntegerコンストラクターではなくを使用することをお勧めします。Integerクラスは、オブジェクトの作成を最小限に抑えるために-128から127までの値をキャッシュします。この記事がするように整数のJavadocは、このことを説明します。stackoverflow.com/a/2974852/871012
これは私にとってreplで機能します。
(読み取り文字列 "123")
=> 123
read-string
ドキュメントごとにコードを実行できます:clojuredocs.org/clojure.core/read-string
私の知る限り、あなたの問題に対する標準的な解決策はありません。を使用する次のようなものclojure.contrib.str-utils2/replace
が役立つと思います:
(defn str2int [txt]
(Integer/parseInt (replace txt #"[a-zA-Z]" "")))
1.5
...そしてそれはまた組み込みclojure.string/replace
関数を利用しません。
これは完璧ではないが、ここで何かをだfilter
、Character/isDigit
とInteger/parseInt
。浮動小数点数では機能せず、入力に数字がない場合は失敗するため、おそらくクリーンアップする必要があります。Javaをあまり必要としない、これを行うより良い方法があるといいのですが。
user=> (defn strToInt [x] (Integer/parseInt (apply str (filter #(Character/isDigit %) x))))
#'user/strToInt
user=> (strToInt "45px")
45
user=> (strToInt "45")
45
user=> (strToInt "a")
java.lang.NumberFormatException: For input string: "" (NO_SOURCE_FILE:0)
私はおそらくいくつかのことを要件に追加します:
多分次のようなもの:
(defn parse-int [v]
(try
(Integer/parseInt (re-find #"^\d+" (.toString v)))
(catch NumberFormatException e 0)))
(parse-int "lkjhasd")
; => 0
(parse-int (java.awt.Color. 4 5 6))
; => 0
(parse-int "a5v")
; => 0
(parse-int "50px")
; => 50
そして、おそらくこれを、0以外のユーザー指定のデフォルトを可能にするマルチメソッドにするためのボーナスポイント。
snrobotの答えを拡張します。
(defn string->integer [s]
(when-let [d (re-find #"-?\d+" s)] (Integer. d)))
このバージョンは、例外が発生するのではなく、入力に数字がない場合はnilを返します。
私の質問は、名前を "str-> int"に省略してもよいか、またはこのようなものは常に完全に指定する必要があるかどうかです。
また、(re-seq)
関数を使用すると、戻り値を、入力文字列に存在するすべての数値を順番に含む文字列に拡張できます。
(defn convert-to-int [s]
(->> (re-seq #"\d" s)
(apply str)
(Integer.)))
(convert-to-int "10not123")
=> 10123
(type *1)
=> java.lang.Integer
この質問では、文字列を数値に解析することについて尋ねられます。
(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
などの代わりにドメインに問題がある場合。
より通常の文字列リテラルを数値、つまり、他の非数値文字を持たない文字列に解析しようとしている他の人にとっては。これらは2つの最良のアプローチです。
Java相互運用機能の使用:
(Long/parseLong "333")
(Float/parseFloat "333.33")
(Double/parseDouble "333.3333333333332")
(Integer/parseInt "-333")
(Integer/parseUnsignedInt "333")
(BigInteger. "3333333333333333333333333332")
(BigDecimal. "3.3333333333333333333333333332")
(Short/parseShort "400")
(Byte/parseByte "120")
これにより、ユースケースで重要な場合に、数値を解析する型を正確に制御できます。
Clojure EDNリーダーの使用:
(require '[clojure.edn :as edn])
(edn/read-string "333")
信頼できない入力で安全に使用できないread-string
from clojure.core
とは異なりedn/read-string
、ユーザー入力などの信頼できない入力で実行しても安全です。
タイプを特定に制御する必要がない場合は、Javaの相互運用機能よりも便利です。Clojureが解析できる任意の数値リテラルを解析できます。
;; Ratios
(edn/read-string "22/7")
;; Hexadecimal
(edn/read-string "0xff")
ここに完全なリスト:https : //www.rubberducking.com/2019/05/clojure-for-non-clojure-programmers.html#numbers
単純なケースでは、上記のように、正規表現を使用して最初の数字列を取り出すことができます。
より複雑な状況の場合は、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])
か?
refer-tupelo
はをモデルにrefer-clojure
して(:require [tupelo.core :refer :all])
います。つまり、方法のすべてが含まれているわけではありません。