В Clojure, как я могу преобразовать строку в число? - PullRequest
119 голосов
/ 11 апреля 2011

У меня есть различные строки, некоторые как "45", некоторые как "45px".Как мне конвертировать оба этих числа в число 45?

Ответы [ 12 ]

1 голос
/ 15 апреля 2017

Для простых случаев вы можете просто использовать регулярное выражение, чтобы вытащить первую строку цифр, как указано выше.

Если у вас более сложная ситуация, вы можете использовать библиотеку 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"))))
0 голосов
/ 11 июня 2019

Для тех, кто хочет разобрать более обычный строковый литерал в число, то есть строку, в которой нет других нечисловых символов. Вот два лучших подхода:

Использование взаимодействия с 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 из 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...