Ich bin froh, dass jemand keine Angst hat, einige grundlegende Fragen zu stellen.
Octopusgrabbus
4
+1 - Teil der Herausforderung ist, dass die Clojure-Dokumente diese "grundlegenden" Fragen, die wir in anderen Sprachen für selbstverständlich halten, manchmal nicht beantworten. (Ich hatte die gleiche Frage 3 Jahre später und fand diese).
Glenn
3
@octopusgrabbus - Ich würde gerne wissen, warum Menschen Angst haben, grundlegende Fragen zu stellen.
appshare.co
1
@Zubair Es wird angenommen, dass grundlegende Dinge bereits irgendwo erklärt wurden, sodass Sie höchstwahrscheinlich etwas übersehen haben und Ihre Frage für "kein Forschungsaufwand" herabgestuft wird.
Al.G.
1
Für diejenigen, die von Google hierher kommen und in konvertieren "9"möchten 9, ist dies das Beste, was für mich funktioniert hat : (Integer. "9").
Weltschmerz
Antworten:
79
Dies wird auf 10pxoder funktionierenpx10
(defn parse-int [s](Integer. (re-find #"\d+" s )))
es wird nur die erste fortlaufende Ziffer so analysiert
Gute Antwort! Dies ist meiner Meinung nach besser als die Verwendung von Lesezeichenfolgen. Ich habe meine Antwort geändert, um Ihre Technik zu verwenden. Ich habe auch ein paar kleine Änderungen vorgenommen.
Benjamin Atkin
das gibt mirException in thread "main" java.lang.ClassNotFoundException: Integer.,
maazza
83
Neue Antwort
Ich mag die Antwort von Snrobot besser. Die Verwendung der Java-Methode ist einfacher und robuster als die Verwendung von Lesezeichenfolgen für diesen einfachen Anwendungsfall. Ich habe ein paar kleine Änderungen vorgenommen. Da der Autor negative Zahlen nicht ausschloss, habe ich sie angepasst, um negative Zahlen zuzulassen. Ich habe es auch so gemacht, dass die Nummer am Anfang der Zeichenfolge beginnen muss.
Außerdem habe ich festgestellt, dass Integer / parseInt als Dezimalzahl analysiert wird, wenn kein Radix angegeben wird, selbst wenn führende Nullen vorhanden sind.
Alte Antwort
Erstens, um nur eine Ganzzahl zu analysieren (da dies ein Hit bei Google ist und es sich um gute Hintergrundinformationen handelt):
Ich bin mir nicht sicher, ob Benutzereingaben vom Clojure-Reader als vertrauenswürdig eingestuft werden können, sodass Sie sie auch vor dem Lesen überprüfen können:
Ihre Antwort gefällt mir am besten - schade, dass dies nicht von der Clojure-Kernbibliothek bereitgestellt wird. Eine kleine Kritik - technisch gesehen ifsollten Sie eine sein, whenda es keinen anderen Block in Ihrer FNS gibt.
Quux00
1
Ja, bitte hören Sie nicht auf, nach dem ersten oder zweiten Codefragment zu lesen!
Benjamin Atkin
2
Ein Heads-up zu Zahlen mit führenden Nullen. read-stringinterpretiert sie als oktal: (read-string "08")löst eine Ausnahme aus. Integer/valueOfbehandelt sie als Dezimalzahl: (Integer/valueOf "08")
ergibt
Beachten Sie auch, dass read-stringeine Ausnahme ausgelöst wird, wenn Sie eine leere Zeichenfolge oder etwas wie "29px"
Ilya Boyandin
So wie es sollte. Ich habe die Frage im Titel beantwortet und was die Leute erwarten, wenn sie diese Seite sehen, bevor ich die Frage im Fragenkörper beantwortete. Es ist das letzte Code-Snippet in meiner Antwort.
Vielen Dank. Dies war hilfreich, um ein Produkt in eine Folge von Ziffern aufzuteilen.
Octopusgrabbus
3
Da wir uns für diese Antwort im Java-Land befinden, ist es im Allgemeinen ratsam Integer/valueOf, anstelle des Integer-Konstruktors zu verwenden. Die Integer-Klasse speichert Werte zwischen -128 und 127 zwischen, um die Objekterstellung zu minimieren. Das Integer Javadoc beschreibt dies ebenso wie diesen Beitrag: stackoverflow.com/a/2974852/871012
quux00
15
Dies funktioniert in Repl für mich viel einfacher.
Dies ist ideal für vertrauenswürdige Eingaben, wie z. B. ein Programmierpuzzle. @jerney ist richtig: Achten Sie darauf, es nicht im eigentlichen Code zu verwenden.
Hraban
10
AFAIK gibt es keine Standardlösung für Ihr Problem. Ich denke, etwas wie das Folgende, das verwendet clojure.contrib.str-utils2/replace, sollte helfen:
Nicht empfohlen. Es wird funktionieren, bis jemand darauf wirft 1.5... und es nutzt auch nicht die eingebaute clojure.string/replaceFunktion.
Teer
8
Dies ist nicht perfekt, aber hier ist etwas mit filter, Character/isDigitund Integer/parseInt. Es funktioniert nicht für Gleitkommazahlen und schlägt fehl, wenn die Eingabe keine Ziffer enthält. Sie sollten sie daher wahrscheinlich bereinigen. Ich hoffe, es gibt einen schöneren Weg, der nicht so viel Java beinhaltet.
Durch die Verwendung der (re-seq)Funktion kann der Rückgabewert auch auf eine Zeichenfolge erweitert werden, die alle in der Eingabezeichenfolge vorhandenen Zahlen in der folgenden Reihenfolge enthält:
Bei der Frage geht es darum, eine Zeichenfolge in eine Zahl zu analysieren.
(number? 0.5);;=> true
Aus den obigen Dezimalstellen sollte also auch analysiert werden.
Vielleicht beantworten Sie die Frage jetzt nicht genau, aber für den allgemeinen Gebrauch sollten Sie genau wissen, ob es sich um eine Nummer handelt oder nicht (daher ist "px" nicht zulässig) und den Anrufer mit Nicht-Nummern umgehen lassen, indem Sie nil zurückgeben:
Für alle anderen, die ein normaleres String-Literal in eine Zahl analysieren möchten, dh einen String, der keine anderen nicht numerischen Zeichen enthält. Dies sind die beiden besten Ansätze:
Im Gegensatz zur Verwendung, read-stringbei der clojure.coredie Verwendung bei nicht vertrauenswürdigen Eingaben nicht sicher ist, kann sie bei nicht edn/read-stringvertrauenswürdigen Eingaben wie Benutzereingaben sicher ausgeführt werden.
Dies ist häufig praktischer als das Java-Interop, wenn Sie keine spezifische Kontrolle über die Typen benötigen. Es kann jedes Zahlenliteral analysieren, das Clojure analysieren kann, wie z.
"9"
möchten9
, ist dies das Beste, was für mich funktioniert hat :(Integer. "9")
.Antworten:
Dies wird auf
10px
oder funktionierenpx10
es wird nur die erste fortlaufende Ziffer so analysiert
quelle
Exception in thread "main" java.lang.ClassNotFoundException: Integer.,
Neue Antwort
Ich mag die Antwort von Snrobot besser. Die Verwendung der Java-Methode ist einfacher und robuster als die Verwendung von Lesezeichenfolgen für diesen einfachen Anwendungsfall. Ich habe ein paar kleine Änderungen vorgenommen. Da der Autor negative Zahlen nicht ausschloss, habe ich sie angepasst, um negative Zahlen zuzulassen. Ich habe es auch so gemacht, dass die Nummer am Anfang der Zeichenfolge beginnen muss.
Außerdem habe ich festgestellt, dass Integer / parseInt als Dezimalzahl analysiert wird, wenn kein Radix angegeben wird, selbst wenn führende Nullen vorhanden sind.
Alte Antwort
Erstens, um nur eine Ganzzahl zu analysieren (da dies ein Hit bei Google ist und es sich um gute Hintergrundinformationen handelt):
Sie könnten den Leser benutzen :
Sie können überprüfen, ob es sich um eine Zahl handelt, nachdem sie gelesen wurde:
Ich bin mir nicht sicher, ob Benutzereingaben vom Clojure-Reader als vertrauenswürdig eingestuft werden können, sodass Sie sie auch vor dem Lesen überprüfen können:
Ich glaube, ich bevorzuge die letzte Lösung.
Und nun zu Ihrer spezifischen Frage. So analysieren Sie etwas, das mit einer Ganzzahl beginnt, wie
29px
:quelle
if
sollten Sie eine sein,when
da es keinen anderen Block in Ihrer FNS gibt.read-string
interpretiert sie als oktal:(read-string "08")
löst eine Ausnahme aus.Integer/valueOf
behandelt sie als Dezimalzahl:(Integer/valueOf "08")
read-string
eine Ausnahme ausgelöst wird, wenn Sie eine leere Zeichenfolge oder etwas wie "29px"quelle
Integer/valueOf
, anstelle des Integer-Konstruktors zu verwenden. Die Integer-Klasse speichert Werte zwischen -128 und 127 zwischen, um die Objekterstellung zu minimieren. Das Integer Javadoc beschreibt dies ebenso wie diesen Beitrag: stackoverflow.com/a/2974852/871012Dies funktioniert in Repl für mich viel einfacher.
(Lesezeichenfolge "123")
=> 123
quelle
read-string
kann Code gemäß den Dokumenten ausführen: clojuredocs.org/clojure.core/read-stringAFAIK gibt es keine Standardlösung für Ihr Problem. Ich denke, etwas wie das Folgende, das verwendet
clojure.contrib.str-utils2/replace
, sollte helfen:quelle
1.5
... und es nutzt auch nicht die eingebauteclojure.string/replace
Funktion.Dies ist nicht perfekt, aber hier ist etwas mit
filter
,Character/isDigit
undInteger/parseInt
. Es funktioniert nicht für Gleitkommazahlen und schlägt fehl, wenn die Eingabe keine Ziffer enthält. Sie sollten sie daher wahrscheinlich bereinigen. Ich hoffe, es gibt einen schöneren Weg, der nicht so viel Java beinhaltet.quelle
Ich würde wahrscheinlich ein paar Dinge zu den Anforderungen hinzufügen:
Vielleicht so etwas wie:
und dann vielleicht Bonuspunkte dafür, dass dies eine Multi-Methode ist, die einen vom Benutzer angegebenen Standardwert außer 0 zulässt.
quelle
Die Antwort von Snrobot erweitern:
Diese Version gibt null zurück, wenn die Eingabe keine Ziffern enthält, anstatt eine Ausnahme auszulösen.
Meine Frage ist, ob es akzeptabel ist, den Namen mit "str-> int" abzukürzen, oder ob solche Dinge immer vollständig spezifiziert werden sollten.
quelle
Durch die Verwendung der
(re-seq)
Funktion kann der Rückgabewert auch auf eine Zeichenfolge erweitert werden, die alle in der Eingabezeichenfolge vorhandenen Zahlen in der folgenden Reihenfolge enthält:(defn convert-to-int [s] (->> (re-seq #"\d" s) (apply str) (Integer.)))
(convert-to-int "10not123")
=>10123
(type *1)
=>java.lang.Integer
quelle
Bei der Frage geht es darum, eine Zeichenfolge in eine Zahl zu analysieren.
Aus den obigen Dezimalstellen sollte also auch analysiert werden.
Vielleicht beantworten Sie die Frage jetzt nicht genau, aber für den allgemeinen Gebrauch sollten Sie genau wissen, ob es sich um eine Nummer handelt oder nicht (daher ist "px" nicht zulässig) und den Anrufer mit Nicht-Nummern umgehen lassen, indem Sie nil zurückgeben:
Und wenn Floats für Ihre Domain problematisch sind, anstatt zu
Float/parseFloat
setzenbigdec
oder etwas anderes.quelle
Für alle anderen, die ein normaleres String-Literal in eine Zahl analysieren möchten, dh einen String, der keine anderen nicht numerischen Zeichen enthält. Dies sind die beiden besten Ansätze:
Verwenden von Java Interop:
Auf diese Weise können Sie den Typ, in dem Sie die Nummer analysieren möchten, genau steuern, wenn dies für Ihren Anwendungsfall von Bedeutung ist.
Verwenden des Clojure EDN-Lesegeräts:
Im Gegensatz zur Verwendung,
read-string
bei derclojure.core
die Verwendung bei nicht vertrauenswürdigen Eingaben nicht sicher ist, kann sie bei nichtedn/read-string
vertrauenswürdigen Eingaben wie Benutzereingaben sicher ausgeführt werden.Dies ist häufig praktischer als das Java-Interop, wenn Sie keine spezifische Kontrolle über die Typen benötigen. Es kann jedes Zahlenliteral analysieren, das Clojure analysieren kann, wie z.
Vollständige Liste hier: https://www.rubberducking.com/2019/05/clojure-for-non-clojure-programmers.html#numbers
quelle
In einfachen Fällen können Sie einfach eine Regex verwenden, um die erste Ziffernfolge wie oben erwähnt herauszuziehen.
Wenn Sie eine kompliziertere Situation haben, können Sie die InstaParse-Bibliothek verwenden:
quelle
(t/refer-tupelo)
anstatt den Benutzer dazu zu bringen(:require [tupelo.core :refer :all])
?refer-tupelo
ist nachempfundenrefer-clojure
, da es nicht alles enthält, was der Weg(:require [tupelo.core :refer :all])
tut.