ক্লোজুরে কীভাবে আমি একটি স্ট্রিংকে একটি সংখ্যায় রূপান্তর করতে পারি?


128

আমার কাছে বিভিন্ন স্ট্রিং রয়েছে, কিছু "45" এর মতো, কিছু "45px" এর মতো। আমি কীভাবে এই দুটিকেই 45 নম্বরে রূপান্তর করব?


32
আমি আনন্দিত যে কেউ কেউ কিছু প্রাথমিক প্রশ্ন জিজ্ঞাসা করতে ভয় পায় না।
অক্টোপাসগ্র্যাববাস

4
+1 - চ্যালেঞ্জের অংশটি হ'ল ক্লজুর ডক্স কখনও কখনও এই অন্যান্য "মৌলিক" প্রশ্নগুলিকে সম্বোধন করে না যা আমরা অন্যান্য ভাষায় মঞ্জুর করি। (আমি একই প্রশ্নটি 3 বছর পরে পেয়েছি এবং এটি পেয়েছি)।
গ্লেন

3
@ অক্টোপাসগ্র্যাববাস - আমি "কেন" লোকেদের প্রাথমিক প্রশ্ন জিজ্ঞাসা করতে ভয় পায় তা জানতে আগ্রহী হব?
appshare.co

1
@ জুবায়ের ধারণা করা হয় যে এটি প্রাথমিক বিষয়গুলি ইতিমধ্যে কোথাও ব্যাখ্যা করা হয়েছে যাতে আপনি সম্ভবত কোনও কিছুকে উপেক্ষা করেছেন এবং "প্রশ্নবিদ্ধ প্রচেষ্টা ব্যতীত" আপনার প্রশ্নকে অগ্রাহ্য করা হবে।
আল.জি.

1
রূপান্তর করতে খুঁজছি Google থেকে এখানে আসার তাদের জন্য "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.,
maazza

83

নতুন উত্তর

আমি স্ন্রোবোটের উত্তরটি আরও ভাল পছন্দ করি। এই সাধারণ ব্যবহারের ক্ষেত্রে রিড-স্ট্রিং ব্যবহার করার চেয়ে জাভা পদ্ধতিটি ব্যবহার করা সহজ এবং আরও শক্ত। আমি কয়েকটি ছোট পরিবর্তন করেছি। যেহেতু লেখক নেতিবাচক সংখ্যাগুলি বাতিল করে দেয় না, তাই আমি নেতিবাচক সংখ্যার অনুমতি দেওয়ার জন্য এটিকে সামঞ্জস্য করেছি। আমি এটিও তৈরি করেছি যাতে স্ট্রিংয়ের শুরুতে এটির সংখ্যাটি শুরু হয়।

(defn parse-int [s]
  (Integer/parseInt (re-find #"\A-?\d+" s)))

শীর্ষস্থানীয় শূন্যগুলি থাকা সত্ত্বেও, যখন কোনও রেডিক্স দেওয়া হয় না তখন পূর্ণসংখ্যা / পার্সইন্ট দশমিক হিসাবে পার্স করে।

পুরানো উত্তর

প্রথমত, কেবলমাত্র একটি পূর্ণসংখ্যা পার্স করা (যেহেতু এটি গুগলে হিট এবং এটি ব্যাকগ্রাউন্ডের ভাল তথ্য):

আপনি পাঠক ব্যবহার করতে পারেন :

(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যেহেতু আপনার ফেন্সে অন্য কোনও ব্লক নেই।
quux00

1
হ্যাঁ, দয়া করে প্রথম বা দ্বিতীয় কোড স্নিপেটের পরে পড়া বন্ধ করবেন না!
বেনিয়ামিন আতকিন

2
শীর্ষস্থানীয় শূন্যগুলির সাথে সংখ্যায় একটি শীর্ষস্থান। read-stringতাদেরকে অষ্টাল হিসাবে ব্যাখ্যা করে: (read-string "08")একটি ব্যতিক্রম ছোঁড়ে। Integer/valueOfদশমিক হিসাবে তাদের আচরণ করে: (Integer/valueOf "08")8 পর্যন্ত মূল্যায়ন করে
রুবাসভ

এছাড়াও মনে রাখবেন যে read-stringআপনি যদি একটি খালি স্ট্রিং বা "29px" এর মতো কিছু দেন তবে ব্যতিক্রম ছুঁড়ে
ইলিয়া বয়ানডিন

যেমনটি করা উচিত। আমি শিরোনামে প্রশ্নের উত্তর দিয়েছি, এবং প্রশ্ন সংস্থায় প্রশ্নের উত্তর দেওয়ার আগে লোকেরা এই পৃষ্ঠাটি দেখলে তারা কী প্রত্যাশা করে। এটি আমার উত্তরটির শুরুর শেষ কোড স্নিপেট।
বেঞ্জামিন আটকিন

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 এর মধ্যে অবজেক্ট তৈরিকে কমাতে মানগুলি ক্যাশে করে। : পূর্ণসংখ্যা Javadoc এই বর্ণনা পোস্টটি মতো stackoverflow.com/a/2974852/871012
quux00

15

এটি আমার পক্ষে প্রত্যক্ষভাবে কাজ করে, আরও অনেক সোজা এগিয়ে।

(পড়ার স্ট্রিং "123")

=> 123


1
ব্যবহারকারীর ইনপুট দিয়ে এটি ব্যবহারে সতর্কতা অবলম্বন করুন। read-stringদস্তাবেজগুলির জন্য কোড সম্পাদন
জার্নি

এটি বিশ্বস্ত ইনপুট যেমন দুর্দান্ত একটি প্রোগ্রামিং ধাঁধা জন্য দুর্দান্ত। @ জার্নি ঠিক বলেছেন: আসল কোডে এটি ব্যবহার না করার বিষয়ে সতর্ক হন।
হারাবান

10

আফাইক আপনার সমস্যার কোনও মানক সমাধান নেই। আমি মনে করি নিম্নলিখিতগুলির মতো কিছু ব্যবহার করে যা ব্যবহার করা 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" সংক্ষেপে গ্রহণযোগ্য কিনা, বা যদি এর মতো জিনিসগুলি সর্বদা সম্পূর্ণ নির্দিষ্ট করা উচিত should


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

সুতরাং উপরের দশমিকগুলি থেকে পাশাপাশি পার্স করা উচিত।

সম্ভবত এখন প্রশ্নের সঠিক উত্তর না দেওয়া, তবে সাধারণ ব্যবহারের জন্য আমি মনে করি যে এটি একটি নম্বর কিনা বা না (তাই "পিএক্স" অনুমোদিত নয়) এবং কলারকে শূন্যতার সাথে ফিরে আসার মাধ্যমে অ-সংখ্যাগুলি পরিচালনা করতে আপনি কঠোর হতে চান:

(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")

এটি যখন আপনার ব্যবহারের ক্ষেত্রে গুরুত্বপূর্ণ তখন আপনি সংখ্যাকে পার্স করতে চান ঠিক সেই ধরণের নিয়ন্ত্রণ করতে দেয়।

ক্লোজার ইডিএন পাঠক ব্যবহার করে:

(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

সাধারণ ক্ষেত্রে আপনি উপরে বর্ণিত অঙ্কের প্রথম স্ট্রিংটি বের করার জন্য কেবল একটি রেজেেক্স ব্যবহার করতে পারেন।

আপনার যদি আরও জটিল পরিস্থিতি থাকে তবে আপনি ইন্সটাপার্স লাইব্রেরিটি ব্যবহার করতে চাইতে পারেন:

(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])
অ্যালান থম্পসন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.