Clojure में मैं एक स्ट्रिंग को एक संख्या में कैसे बदल सकता हूं?


128

मेरे पास विभिन्न तार हैं, कुछ "45" की तरह, कुछ "45px" जैसे। कैसे मैं इन दोनों को 45 नंबर में बदलूं?


32
मुझे खुशी है कि कोई व्यक्ति कुछ बुनियादी सवाल पूछने से डरता नहीं है।
ऑक्टोपसग्राबस

4
+1 - चुनौती का हिस्सा यह है कि क्लोजर डॉक्स कभी-कभी इन "मूल" प्रश्नों को संबोधित नहीं करते हैं जो हम अन्य भाषाओं में दिए गए हैं। (मैं 3 साल बाद एक ही सवाल था और यह पाया गया)।
ग्लेन

3
@octopusgrabbus - मुझे यह जानने में दिलचस्पी होगी कि "लोग" बुनियादी सवाल पूछने से क्यों डरते हैं?
appshare.co

1
@ ज़ुबैर माना जाता है कि बुनियादी चीजें कहीं न कहीं पहले से ही समझाई जाती हैं इसलिए आप शायद सबसे ज्यादा कुछ अनदेखी करते हैं और आपके सवाल को "बिना किसी शोध प्रयास" के नकार दिया जाएगा।
अल.जी.

1
कन्वर्ट करने के लिए देख गूगल से यहाँ आने वाले लोगों के लिए "9"में 9, यह सबसे अच्छी बात यह है कि मेरे लिए काम किया है: (Integer. "9")
वेल्ट्सकेमरज़

जवाबों:


79

यह 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.,
माज़ा

83

नया जवाब

मुझे स्नोबोट का जवाब बेहतर लगता है। जावा विधि का उपयोग करना सरल है और इस सरल उपयोग के मामले में रीड-स्ट्रिंग का उपयोग करने से अधिक मजबूत है। मैंने कुछ छोटे बदलाव किए। चूंकि लेखक ने नकारात्मक संख्याओं को खारिज नहीं किया, इसलिए मैंने इसे नकारात्मक संख्याओं की अनुमति देने के लिए समायोजित किया। मैंने इसे भी बनाया है इसलिए इसे स्ट्रिंग की शुरुआत में नंबर की आवश्यकता है।

(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 में कोई और ब्लॉक नहीं है।
quux00

1
हाँ, कृपया पहले या दूसरे कोड स्निपेट के बाद पढ़ना बंद न करें!
बेंजामिन एटकिन

2
प्रमुख शून्य के साथ संख्याओं पर एक सिर-अप। read-stringउन्हें अष्टक के रूप में व्याख्या करता है: (read-string "08")एक अपवाद फेंकता है। Integer/valueOfउन्हें दशमलव के रूप में व्यवहार करता है: (Integer/valueOf "08")8 पर मूल्यांकन करता है
रुबसोव

ध्यान दें कि read-stringएक अपवाद फेंकता है अगर आप इसे एक खाली स्ट्रिंग या "29px" की तरह कुछ देते हैं
Ilya Boyandin

जैसा होना चाहिए। मैंने शीर्षक में प्रश्न का उत्तर दिया, और लोग इस पृष्ठ को देखने से क्या उम्मीद करते हैं, इससे पहले कि मैं प्रश्न शरीर में प्रश्न का उत्तर दूं। यह मेरे जवाब के शरीर में अंतिम कोड स्निपेट है।
बेंजामिन एटकिन

30
(defn parse-int [s]
  (Integer. (re-find #"[0-9]*" s)))

user> (parse-int "10px")
10
user> (parse-int "10")
10

धन्यवाद। यह मेरे उत्पाद को अंकों के अनुक्रम में विभाजित करने में सहायक था।
ऑक्टोपसग्राबस

3
चूँकि हम इस उत्तर के लिए जावा भूमि में हैं, इसलिए आमतौर पर इसका उपयोग करने की सलाह दी जाती है Integer/valueOf, बजाय कि इंटीजर कंस्ट्रक्टर के। इंटेगर वर्ग ऑब्जेक्ट निर्माण को कम करने के लिए -128 और 127 के बीच मूल्य रखता है।
इंटेगर जावदोक

15

यह मेरे लिए जवाब में काम करता है, बहुत सीधे आगे।

(रीड-स्ट्रिंग "123")

=> 123


1
उपयोगकर्ता इनपुट के साथ इसका उपयोग करने में सावधानी बरतें। read-stringडॉक्स प्रति कोड निष्पादित कर सकते हैं: clojuredocs.org/clojure.core/read-string
jerney

यह विश्वसनीय इनपुट के लिए बहुत अच्छा है, जैसे एक प्रोग्रामिंग पहेली। @ हर्नी सही है: वास्तविक कोड में इसका उपयोग न करने के लिए सावधान रहें।
हरबन

10

AFAIK आपकी समस्या के लिए कोई मानक समाधान नहीं है। मुझे लगता है कि निम्नलिखित कुछ है, जो उपयोग करता है clojure.contrib.str-utils2/replace, मदद करनी चाहिए:

(defn str2int [txt]
  (Integer/parseInt (replace txt #"[a-zA-Z]" "")))

सिफारिश नहीं की गई। यह तब तक काम करेगा जब तक कोई 1.5इसे फेंकता नहीं है ... और यह बिल्ट-इन clojure.string/replaceफ़ंक्शन का उपयोग नहीं करता है ।
टार

8

यह सही नहीं है, लेकिन यहाँ कुछ है 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)

4

मैं शायद आवश्यकताओं में कुछ चीजें जोड़ूंगा:

  • एक अंक के साथ शुरू करना है
  • खाली आदानों को सहन करना पड़ता है
  • किसी भी वस्तु को पारित किया जा रहा है (मानक मानक है)

शायद कुछ इस तरह:

(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 से भिन्न उपयोगकर्ता-प्रदत्त डिफ़ॉल्ट के लिए अनुमति देता है।


4

स्नोबोट के उत्तर पर विस्तार:

(defn string->integer [s] 
  (when-let [d (re-find #"-?\d+" s)] (Integer. d)))

यदि कोई अपवाद नहीं है, तो इनपुट में कोई अंक नहीं होने पर यह संस्करण शून्य हो जाता है।

मेरा प्रश्न यह है कि क्या नाम को "str-> int" में संक्षिप्त करना स्वीकार्य है, या यदि इस तरह की चीजें हमेशा पूरी तरह से निर्दिष्ट होनी चाहिए।


3

(re-seq)फ़ंक्शन का उपयोग करके इनपुट स्ट्रिंग में मौजूद सभी नंबरों के लिए वापसी मान को बढ़ा सकते हैं:

(defn convert-to-int [s] (->> (re-seq #"\d" s) (apply str) (Integer.)))

(convert-to-int "10not123") => 10123

(type *1) => java.lang.Integer


3

प्रश्न एक स्ट्रिंग को एक संख्या में पार्स करने के बारे में पूछता है।

(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या कुछ और के बजाय आपके डोमेन के लिए समस्याग्रस्त है।


3

किसी और के लिए एक संख्या में अधिक सामान्य स्ट्रिंग शाब्दिक पार्स करने की तलाश में, वह है, एक स्ट्रिंग जिसमें अन्य गैर-संख्यात्मक वर्ण नहीं हैं। ये दो सर्वोत्तम दृष्टिकोण हैं:

जावा इंटरॉप का उपयोग करना:

(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


2

सरल मामलों के लिए आप बस ऊपर बताए अनुसार अंकों के पहले तार को बाहर निकालने के लिए एक रेगेक्स का उपयोग कर सकते हैं।

यदि आपके पास अधिक जटिल स्थिति है तो आप 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

refer-tupeloके बाद मॉडलिंग की जाती है refer-clojure, जिसमें वह सब कुछ शामिल नहीं करता है जिस तरह से (:require [tupelo.core :refer :all])करता है।
एलन थॉम्पसन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.