मेरे पास विभिन्न तार हैं, कुछ "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.,
मुझे स्नोबोट का जवाब बेहतर लगता है। जावा विधि का उपयोग करना सरल है और इस सरल उपयोग के मामले में रीड-स्ट्रिंग का उपयोग करने से अधिक मजबूत है। मैंने कुछ छोटे बदलाव किए। चूंकि लेखक ने नकारात्मक संख्याओं को खारिज नहीं किया, इसलिए मैंने इसे नकारात्मक संख्याओं की अनुमति देने के लिए समायोजित किया। मैंने इसे भी बनाया है इसलिए इसे स्ट्रिंग की शुरुआत में नंबर की आवश्यकता है।
(defn parse-int [s]
(Integer/parseInt (re-find #"\A-?\d+" s)))
इसके अतिरिक्त मैंने पाया कि पूर्णांक / parseInt को दशमलव के रूप में देखा जाता है जब कोई मूलांक नहीं दिया जाता है, भले ही प्रमुख शून्य हों।
सबसे पहले, केवल एक पूर्णांक को पार्स करने के लिए (क्योंकि यह Google पर हिट है और यह अच्छी पृष्ठभूमि की जानकारी है):
आप पाठक का उपयोग कर सकते हैं :
(read-string "9") ; => 9
आप पढ़ सकते हैं कि यह पढ़ने के बाद एक संख्या है:
(defn str->int [str] (if (number? (read-string str))))
मुझे यकीन नहीं है कि अगर क्लोजर रीडर द्वारा उपयोगकर्ता इनपुट पर भरोसा किया जा सकता है तो आप इसे पढ़ने से पहले जांच सकते हैं:
(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
होना चाहिए when
क्योंकि आपके fns में कोई और ब्लॉक नहीं है।
read-string
उन्हें अष्टक के रूप में व्याख्या करता है: (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
, बजाय कि इंटीजर कंस्ट्रक्टर के। इंटेगर वर्ग ऑब्जेक्ट निर्माण को कम करने के लिए -128 और 127 के बीच मूल्य रखता है।
यह मेरे लिए जवाब में काम करता है, बहुत सीधे आगे।
(रीड-स्ट्रिंग "123")
=> 123
read-string
डॉक्स प्रति कोड निष्पादित कर सकते हैं: clojuredocs.org/clojure.core/read-string
AFAIK आपकी समस्या के लिए कोई मानक समाधान नहीं है। मुझे लगता है कि निम्नलिखित कुछ है, जो उपयोग करता है 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
। यह फ्लोटिंग पॉइंट नंबरों के लिए काम नहीं करेगा और यह विफल रहता है अगर इनपुट में कोई अंक नहीं है, तो आपको शायद इसे साफ करना चाहिए। मुझे आशा है कि ऐसा करने का एक अच्छा तरीका है जिसमें इतना जावा शामिल नहीं है।
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 से भिन्न उपयोगकर्ता-प्रदत्त डिफ़ॉल्ट के लिए अनुमति देता है।
स्नोबोट के उत्तर पर विस्तार:
(defn string->integer [s]
(when-let [d (re-find #"-?\d+" s)] (Integer. d)))
यदि कोई अपवाद नहीं है, तो इनपुट में कोई अंक नहीं होने पर यह संस्करण शून्य हो जाता है।
मेरा प्रश्न यह है कि क्या नाम को "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" की अनुमति नहीं है) और फोन करने वाले को नॉन-नॉयल करके नॉन-नंबर्स को हैंडल करने दें:
(defn str->number [x]
(when-let [num (re-matches #"-?\d+\.?\d*" x)]
(try
(Float/parseFloat num)
(catch Exception _
nil))))
और अगर फ़्लैट Float/parseFloat
पुट bigdec
या कुछ और के बजाय आपके डोमेन के लिए समस्याग्रस्त है।
किसी और के लिए एक संख्या में अधिक सामान्य स्ट्रिंग शाब्दिक पार्स करने की तलाश में, वह है, एक स्ट्रिंग जिसमें अन्य गैर-संख्यात्मक वर्ण नहीं हैं। ये दो सर्वोत्तम दृष्टिकोण हैं:
जावा इंटरॉप का उपयोग करना:
(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
, clojure.core
जिससे उपयोग करने के विपरीत , edn/read-string
उपयोगकर्ता इनपुट जैसे अविश्वसनीय इनपुट पर चलाने के लिए सुरक्षित है।
यदि आप प्रकारों के विशिष्ट नियंत्रण की आवश्यकता नहीं है तो यह अक्सर अधिक सुविधाजनक होता है तो जावा इंटरॉप। यह किसी भी संख्या को शाब्दिक रूप से पार्सल कर सकता है जैसे कि क्लीज्योर को पार्स कर सकता है:
;; 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])
करता है।