gibt es eine Lib, die mir einen String Expression in Java Code umwandelt und somit das Ergebnis prüft?
Eine Expression kann ein String sein oder auch mathematische Formeln.
Konkret:
Ich habe eine Bedingung:
1) "A" = "A"
2) 1+1 = 10
3) A = A
Nun möchte ich dies prüfen lassen.
Also sowas wie:
EvalEx is a handy expression evaluator for Java, that allows to evaluate simple mathematical and boolean expressions. - ezylang/EvalEx
github.com
Oder man nutzt einfach die JavaScript Engine (ScriptEngineManager Klasse und nashorn Engine. Wobei nashorn engine it Java 14 entfernt wurde und ab Java 11 gibt es eine Warnung. Ist aber immer noch verfügbar als externe Library: https://mvnrepository.com/artifact/org.openjdk.nashorn/nashorn-core
Danke...
Die zweite Lib (EvalEx) habe ich mir schon angeschaut...
Aber wie geht das mit Strings? Mit Zahlen habe ich ein paar Tests probiert und das sah gut aus...
Sollte sich wie unter https://github.com/uklimaschewski/EvalEx#custom-functions-with-string-parameters beschrieben, realisieren lassen. Du kannst auch eigene Operatoren definieren, allerdings nicht überladen. Wenn Du also den Gleichheitsoperator für Zahlen und Strings gleichermaßen verwenden willst, könnte es funktionieren, wenn Du im Beispiel erstmal versuchst, die beiden Operanden als Zahlen zu behandeln und wenn das nicht funktioniert, den String-Vergleich durchzuführen.
Das entspricht doch genau dem Besipiel, oder sehe ich hier was falsch? Du musst lediglich einen passenden Funktionsnamen wählen und in lazyEval statt equals halt z. B. contains etc. verwenden.
Das entspricht doch genau dem Besipiel, oder sehe ich hier was falsch? Du musst lediglich einen passenden Funktionsnamen wählen und in lazyEval statt equals halt z. B. contains etc. verwenden.
ok, wenn ich es richtig verstehe müsste ich dann eben verschiedene Funktionen erstellen (CONTAINS, EQUAL...)
Dann müsste meine Expression aber auch so sein:
Wenn, dann willst Du einen String auswerten, in dem etwas wie "Test"="Test" steht. D. h. das, was Du da stehen hast, ist nicht das result sondern der input und das lässt sich, wie in #4 beschrieben, mit einem eigenen "="-Operator auswerten lassen.
Wenn, dann willst Du einen String auswerten, in dem etwas wie "Test"="Test" steht. D. h. das, was Du da stehen hast, ist nicht das result sondern der input und das lässt sich, wie in #4 beschrieben, mit einem eigenen "="-Operator auswerten lassen.
Wir drehen uns im Kreis. Nimm das Beispiel aus https://github.com/uklimaschewski/EvalEx#custom-functions-with-string-parameters und passe es auf Operatoren an (z. B. statt AbstractLazyFunction eben AbstractLazyOperator verwenden und natürlich nicht addLazyFunction verwenden). Ich kenn die Lib auch nicht, und schaue nur die in den Quellcode rein. Mit etwas Glück könnte es klappen.
publicstaticAbstractLazyOperatorcreateStringOperator(){returnnewAbstractLazyOperator("=",30,true){privateLazyNumber ZERO =newLazyNumber(){publicBigDecimaleval(){returnBigDecimal.ZERO;}publicStringgetString(){return"0";}};privateLazyNumber ONE =newLazyNumber(){publicBigDecimaleval(){returnBigDecimal.ONE;}publicStringgetString(){returnnull;}};@OverridepublicLazyNumbereval(LazyNumber v1,LazyNumber v2){if(v1.getString().equals(v2.getString())){return ZERO;}return ONE;}};}
Java:
Expression e =newExpression("\"TEST\" = \"TEST\"");
e.addOperator(ExpressionFunctions.createStringOperator());
e.eval();
Bekomme aber in der Klasse Expression eine NPE:
Zeile 507:
publicstaticAbstractLazyOperatorcreateStringOperator(){returnnewAbstractLazyOperator("=",30,true){privateLazyNumber ZERO =newLazyNumber(){publicBigDecimaleval(){returnBigDecimal.ZERO;}publicStringgetString(){return"0";}};privateLazyNumber ONE =newLazyNumber(){publicBigDecimaleval(){returnBigDecimal.ONE;}publicStringgetString(){returnnull;}};@OverridepublicLazyNumbereval(LazyNumber v1,LazyNumber v2){if(v1.getString().equals(v2.getString())){return ZERO;}return ONE;}};}
Java:
Expression e =newExpression("\"TEST\" = \"TEST\"");
e.addOperator(ExpressionFunctions.createStringOperator());
e.eval();
Bekomme aber in der Klasse Expression eine NPE:
Zeile 507:
wenn du dich nicht mehr in deinem eigenen code auskennst wie soltte es dann ein anderer können...
bennnen deine expression vllt nicht mit "e" usw.. vllt entsteht ein lesbarer code
wenn du dich nicht mehr in deinem eigenen code auskennst wie soltte es dann ein anderer können...
bennnen deine expression vllt nicht mit "e" usw.. vllt entsteht ein lesbarer code
deine Variablen Bezeichnung ist nett gesagt so schlecht gewählt dass jeder der sich halbwegs einlesen möchte sich maximal schwer tut um irgendwas zu verstehen ... wenn eine Variable 1 Zeile im Editor einnehmen würde um absolut klar zu sagen wofür sie gut ist dann hätte man was aber so muss man bei den "unwichtigen" sachen raten und hoffen dass sie richtig sind
zb was soll ein aussenstehender mit einem getString anfangen wenn man sowas hinballert
Java:
publicStringgetString(){returnnull;}
also das ist doch einfach nur ein troll
Java:
publicStringgetString(){return"0";}
dann kommt sowas... also von allen grundsätzen von java die ich bis jetzt im studium und hier gelernt habe ist das eifnach nur meilenweit entfernt
für was hast du denn Objekte wenn sie sowieso das gleiche zurück geben
dann kannst dir gleich die Statische methode
anlegen dann hast das selbe .. es hilft halt nicht wenn man weis der gegenüber kann es eigentlcih aber machts mit absicht so dass man extra lange braucht um sich einzulesen
Unabhängig ob es mit dem Problem zu tun hat es ist nicht sinnvoll ... hab noch nie eine methode gesehen die sinnvoll ist die immer null zurück gibt egal was rein kommt ausser eine void methode
Nix. Da fehlt m. E. ein null-Check in Expression.java. Mach mal testweise Klammern außenrum, um zu testen, ob das mti dem Operator überhaupt funktioniert. Falls ja, kannst Du Zeile 507 in Expression.java ändern zu
Den Code der Library zu ändern ist nicht unbedingt der Weg, den ich zuerst gehen würde. Ich würde da erst noch etwas tiefer schauen, ob und was da überhaupt passiert.
Kommt er in den eigenen Code überhaupt rein? (Sprich: wird der vorhandene Operator = ersetzt?)
Die Library ist ja nicht so groß, so dass man sich einen ersten Überblick verschaffen könnte. Das wäre auf jeden Fall der erste Schritt, den ich gehen würde, ehe ich an der Library irgendwelche Änderungen vornehmen würde ...
Den Code der Library zu ändern ist nicht unbedingt der Weg, den ich zuerst gehen würde. Ich würde da erst noch etwas tiefer schauen, ob und was da überhaupt passiert.
Kommt er in den eigenen Code überhaupt rein? (Sprich: wird der vorhandene Operator = ersetzt?)
Die Library ist ja nicht so groß, so dass man sich einen ersten Überblick verschaffen könnte. Das wäre auf jeden Fall der erste Schritt, den ich gehen würde, ehe ich an der Library irgendwelche Änderungen vornehmen würde ...
Die createStringOperator() Methode ist natürlich ausgeführt, aber die ist uninteressant. Interessant wäre, ob er in die eval Methode rein kommt. Und das ist nicht der Fall.
Bei dem Ausdruck "Test" = "Test" kommt er noch nicht einmal durch den Tokenizer.
Das Du Dir das alles schon etwas näher angesehen hast, war mir irgenwie durchaus klar. Aber Ich sehe hier im Thread nicht wirklich etwas sinnvolles bei raus kommen im Augenblick ...
Durch die Klammern funktioniert es, aber ob das für ihn ausreichend ist?
Ansonsten die precendence noch verändern. Damit es für Dinge wie 2 = 1 + 1 auch funktioniert.
Und dann in eval noch die Rückgabe umdrehen - bei Gleichheit sollte 1 und sonst die 0 zurück gegeben werden ...
könnte das auch für andere Ausdrücke passen (Denn ich vermute ja, dass er eine Lösung haben will, die sowohl 2 = 1 + 1 als auch das "Test" = "Test" auswerten kann...
@mrBrown Und Du willst jetzt den Tokenizer anpassen / verbessern? Den TE daran spielen lassen und da etwas verändern lassen, halte ich nicht wirklich für zielführend
@mrBrown weniger Auch ich will nix anpassen, ich schau mir nur den Code an und sehe, dass es an der Stelle einen null-Check braucht, damit der Ausdruck mit einem Anführungszeichen beginnen kann.
Sorry, Ich weiss auch nicht: irgendwie werfe ich euch immer durcheinander und keine Ahnung, warum ich das immer durcheinander bringe, wenn ich darauf nicht so achte Ist aber nicht böse gemeint.
Sorry, Ich weiss auch nicht: irgendwie werfe ich euch immer durcheinander und keine Ahnung, warum ich das immer durcheinander bringe, wenn ich darauf nicht so achte Ist aber nicht böse gemeint.
e = new Expression("\"Test\" = \"Test\"");
i = e.getExpressionTokenizer();
assertToken("Test", TokenType.STRINGPARAM, i.next());
assertToken("=", TokenType.OPERATOR, i.next());
assertToken("Test", TokenType.STRINGPARAM, i.next());
assertFalse(i.hasNext());
}[/CODE]
Aber nun will er die Auswertung nicht. Er scheint die STRINGPARAM nicht bei einem equals anzunehmen:
Java:
Expression expression =newExpression("\"a\" = \"a\"");BigDecimal result = expression.eval();
führt zu
Code:
com.udojava.evalex.Expression$ExpressionException: Missing parameter(s) for operator =
at com.udojava.evalex.Expression.validate(Expression.java:1958)
at com.udojava.evalex.Expression.getRPN(Expression.java:1917)
at com.udojava.evalex.Expression.eval(Expression.java:1509)
at com.udojava.evalex.Expression.eval(Expression.java:1494)
at com.udojava.evalex.TestEval.testStringComparison(TestEval.java:19)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:221)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Da habe ich mich aber jetzt auf die Schnelle nicht einlesen können. Ich finde den Code auch so nicht wirklich gut lesbar. Da sehe ich wenig Sinn, so auf die Schnelle noch etwas rum zu spielen sondern würde dann erst noch einiges umstellen. Das geht aber über ein schnelles experimentieren hinaus aus meiner Sicht und wenn man sowas macht, dann nur mit clone auf GitHub (und da habe ich irgendwie auch keine Lust zu )