Cieszę się, że ktoś nie boi się zadać kilku podstawowych pytań.
octopusgrabbus
4
+1 - częścią wyzwania jest to, że dokumenty Clojure czasami nie odnoszą się do tych „podstawowych” pytań, które w innych językach przyjmujemy za pewnik. (Miałem to samo pytanie 3 lata później i znalazłem to).
Glenn
3
@octopusgrabbus - chciałbym wiedzieć, „dlaczego” ludzie boją się zadawać podstawowe pytania?
appshare.co
1
@Zubair przypuszcza się, że podstawowe rzeczy są już gdzieś wyjaśnione, więc najprawdopodobniej coś przeoczyłeś, a twoje pytanie zostanie odrzucone za „brak wysiłku badawczego”.
Al.G.
1
Dla tych, którzy przyjeżdżają tu z Google chce przekształcić "9"się 9, jest to najlepsza rzecz, że pracował dla mnie (Integer. "9").
weltschmerz
Odpowiedzi:
79
To zadziała na 10pxlubpx10
(defn parse-int [s](Integer. (re-find #"\d+" s )))
Niezła odpowiedź! Moim zdaniem jest to lepsze niż używanie ciągu do odczytu. Zmieniłem odpowiedź, żeby użyć twojej techniki. Wprowadziłem również kilka drobnych zmian.
Benjamin Atkin
to daje miException in thread "main" java.lang.ClassNotFoundException: Integer.,
maazza
83
Nowa odpowiedź
Odpowiedź snrobota podoba mi się bardziej. Użycie metody Java jest prostsze i bardziej niezawodne niż użycie ciągu do odczytu w tym prostym przypadku użycia. Zrobiłem kilka drobnych zmian. Ponieważ autor nie wykluczył liczb ujemnych, dostosowałem to, aby dopuszczać liczby ujemne. Zrobiłem to również, więc wymaga, aby numer zaczynał się na początku ciągu.
Najbardziej podoba mi się twoja odpowiedź - szkoda, że nie zapewnia tego biblioteka rdzenia clojure. Jedna drobna krytyka - technicznie rzecz biorąc, ifpowinieneś być a, whenponieważ w twoich fns nie ma innego bloku.
quux00
1
Tak, nie przestawaj czytać po pierwszym lub drugim fragmencie kodu!
Benjamin Atkin
2
Heads-up z liczbami z zerami na początku. read-stringinterpretuje je jako ósemkowe: (read-string "08")zgłasza wyjątek. Integer/valueOftraktuje je jako dziesiętne: (Integer/valueOf "08")
zwraca
Zauważ również, że read-stringzgłasza wyjątek, jeśli podasz mu pusty ciąg lub coś w rodzaju „29px”
Ilya Boyandin
Jak powinno. Odpowiedziałem na pytanie w tytule i czego ludzie oczekują, gdy zobaczą tę stronę, zanim odpowiedziałem na pytanie w treści pytania. To ostatni fragment kodu w treści mojej odpowiedzi.
Dzięki. Pomogło mi to w podzieleniu produktu na ciąg cyfr.
octopusgrabbus
3
Ponieważ jesteśmy w krainie Java, aby uzyskać tę odpowiedź, ogólnie zaleca się użycie Integer/valueOfzamiast konstruktora Integer. Klasa Integer buforuje wartości od -128 do 127, aby zminimalizować tworzenie obiektów. Integer Javadoc opisuje to, podobnie jak ten post: stackoverflow.com/a/2974852/871012
quux00
15
Działa to w odpowiedzi dla mnie, znacznie prostsze.
jest to świetne rozwiązanie w przypadku zaufanych danych wejściowych, na przykład układanki programistycznej. @jerney ma rację: uważaj, aby nie używać go w rzeczywistym kodzie.
hraban
10
AFAIK nie ma standardowego rozwiązania Twojego problemu. Myślę, że clojure.contrib.str-utils2/replacepowinno pomóc coś takiego jak poniższe, które używa :
Niepolecane. Będzie działać, dopóki ktoś 1.5w nią nie rzuci ... a także nie korzysta z wbudowanej clojure.string/replacefunkcji.
tar
8
To nie jest idealne, ale tutaj jest coś filter, Character/isDigiti Integer/parseInt. Nie będzie działać dla liczb zmiennoprzecinkowych i nie powiedzie się, jeśli na wejściu nie ma cyfry, więc prawdopodobnie powinieneś ją wyczyścić. Mam nadzieję, że istnieje lepszy sposób na zrobienie tego, który nie wymaga tak dużo Java.
Tak więc z powyższych liczb dziesiętnych należy również przeanalizować.
Być może nie do końca odpowiadając teraz na pytanie, ale myślę, że do ogólnego użytku chciałbyś być ścisły co do tego, czy jest to liczba, czy nie (więc „px” jest niedozwolone) i pozwól dzwoniącemu obsłużyć inne niż liczby, zwracając zero:
Dla każdego, kto chce przeanalizować bardziej normalny literał String na liczbę, to znaczy ciąg, który nie ma innych znaków nienumerycznych. Oto dwa najlepsze podejścia:
W przeciwieństwie do korzystania read-stringz clojure.corektórego nie jest bezpieczne w przypadku niezaufanych danych wejściowych, edn/read-stringmożna bezpiecznie uruchomić na niezaufanych danych wejściowych, takich jak dane wejściowe użytkownika.
Jest to często wygodniejsze niż współdziałanie języka Java, jeśli nie potrzebujesz określonej kontroli nad typami. Może analizować dowolny literał liczbowy, który Clojure może przeanalizować, taki jak:
"9"
się9
, jest to najlepsza rzecz, że pracował dla mnie(Integer. "9")
.Odpowiedzi:
To zadziała na
10px
lubpx10
przeanalizuje tylko pierwszą ciągłą cyfrę
źródło
Exception in thread "main" java.lang.ClassNotFoundException: Integer.,
Nowa odpowiedź
Odpowiedź snrobota podoba mi się bardziej. Użycie metody Java jest prostsze i bardziej niezawodne niż użycie ciągu do odczytu w tym prostym przypadku użycia. Zrobiłem kilka drobnych zmian. Ponieważ autor nie wykluczył liczb ujemnych, dostosowałem to, aby dopuszczać liczby ujemne. Zrobiłem to również, więc wymaga, aby numer zaczynał się na początku ciągu.
Dodatkowo odkryłem, że Integer / parseInt analizuje jako dziesiętne, gdy nie jest podana żadna podstawa, nawet jeśli występują zera wiodące.
Stara odpowiedź
Po pierwsze, aby przeanalizować tylko liczbę całkowitą (ponieważ jest to hit w Google i dobre informacje w tle):
Możesz użyć czytnika :
Możesz sprawdzić, czy jest to liczba po przeczytaniu:
Nie jestem pewien, czy dane wprowadzane przez użytkownika mogą być zaufane przez czytnik clojure, więc możesz sprawdzić przed przeczytaniem:
Myślę, że wolę ostatnie rozwiązanie.
A teraz do twojego konkretnego pytania. Aby przeanalizować coś, co zaczyna się od liczby całkowitej, na przykład
29px
:źródło
if
powinieneś być a,when
ponieważ w twoich fns nie ma innego bloku.read-string
interpretuje je jako ósemkowe:(read-string "08")
zgłasza wyjątek.Integer/valueOf
traktuje je jako dziesiętne:(Integer/valueOf "08")
read-string
zgłasza wyjątek, jeśli podasz mu pusty ciąg lub coś w rodzaju „29px”źródło
Integer/valueOf
zamiast konstruktora Integer. Klasa Integer buforuje wartości od -128 do 127, aby zminimalizować tworzenie obiektów. Integer Javadoc opisuje to, podobnie jak ten post: stackoverflow.com/a/2974852/871012Działa to w odpowiedzi dla mnie, znacznie prostsze.
(ciąg do odczytu „123”)
=> 123
źródło
read-string
może wykonać kod zgodnie z dokumentacją: clojuredocs.org/clojure.core/read-stringAFAIK nie ma standardowego rozwiązania Twojego problemu. Myślę, że
clojure.contrib.str-utils2/replace
powinno pomóc coś takiego jak poniższe, które używa :źródło
1.5
w nią nie rzuci ... a także nie korzysta z wbudowanejclojure.string/replace
funkcji.To nie jest idealne, ale tutaj jest coś
filter
,Character/isDigit
iInteger/parseInt
. Nie będzie działać dla liczb zmiennoprzecinkowych i nie powiedzie się, jeśli na wejściu nie ma cyfry, więc prawdopodobnie powinieneś ją wyczyścić. Mam nadzieję, że istnieje lepszy sposób na zrobienie tego, który nie wymaga tak dużo Java.źródło
Dodałbym pewnie kilka rzeczy do wymagań:
Może coś takiego:
a następnie być może dodatkowe punkty za uczynienie z tego metody wielu metod, która pozwala na domyślne ustawienie użytkownika inne niż 0.
źródło
Rozwinięcie odpowiedzi snrobota:
Ta wersja zwraca nil, jeśli w danych wejściowych nie ma cyfr, zamiast zgłaszać wyjątek.
Moje pytanie brzmi, czy dopuszczalne jest skrócenie nazwy do „str-> int”, czy też takie rzeczy powinny być zawsze w pełni określone.
źródło
Również użycie
(re-seq)
funkcji może rozszerzyć zwracaną wartość do ciągu zawierającego wszystkie liczby istniejące w ciągu wejściowym w kolejności:(defn convert-to-int [s] (->> (re-seq #"\d" s) (apply str) (Integer.)))
(convert-to-int "10not123")
=>10123
(type *1)
=>java.lang.Integer
źródło
Pytanie dotyczy parsowania łańcucha na liczbę.
Tak więc z powyższych liczb dziesiętnych należy również przeanalizować.
Być może nie do końca odpowiadając teraz na pytanie, ale myślę, że do ogólnego użytku chciałbyś być ścisły co do tego, czy jest to liczba, czy nie (więc „px” jest niedozwolone) i pozwól dzwoniącemu obsłużyć inne niż liczby, zwracając zero:
A jeśli zmiennoprzecinkowe są problematyczne dla Twojej domeny, zamiast
Float/parseFloat
wstawianiabigdec
lub czegoś innego.źródło
Dla każdego, kto chce przeanalizować bardziej normalny literał String na liczbę, to znaczy ciąg, który nie ma innych znaków nienumerycznych. Oto dwa najlepsze podejścia:
Korzystanie z współpracy w języku Java:
Pozwala to precyzyjnie kontrolować typ, w którym chcesz przeanalizować liczbę, gdy ma to znaczenie dla twojego przypadku użycia.
Korzystanie z czytnika Clojure EDN:
W przeciwieństwie do korzystania
read-string
zclojure.core
którego nie jest bezpieczne w przypadku niezaufanych danych wejściowych,edn/read-string
można bezpiecznie uruchomić na niezaufanych danych wejściowych, takich jak dane wejściowe użytkownika.Jest to często wygodniejsze niż współdziałanie języka Java, jeśli nie potrzebujesz określonej kontroli nad typami. Może analizować dowolny literał liczbowy, który Clojure może przeanalizować, taki jak:
Pełna lista tutaj: https://www.rubberducking.com/2019/05/clojure-for-non-clojure-programmers.html#numbers
źródło
W prostych przypadkach możesz po prostu użyć wyrażenia regularnego, aby wyciągnąć pierwszy ciąg cyfr, jak wspomniano powyżej.
Jeśli masz bardziej skomplikowaną sytuację, możesz skorzystać z biblioteki InstaParse:
źródło
(t/refer-tupelo)
zamiast nakłaniać użytkownika do działania(:require [tupelo.core :refer :all])
?refer-tupelo
jest wzorowany na tymrefer-clojure
, że nie obejmuje wszystkiego, co(:require [tupelo.core :refer :all])
robi.