Frage

Was ist der beste war ein Ausdruck wie folgt zu bewerten:
(A und B) oder (A und C) oder (nicht B und C)
oder in (A && B) || (A && C) || (! B && C)

Zur Laufzeit, ich war die Planung auf die obigen Ausdrücke auf die folgende Umwandlung:
(Wahr und falsch) oder (wahr und falsch) oder (Nicht falsch und True)
oder in (True && False) || (True && False) || (! Falsch && True)

Bedingungen: 1) Der logische Ausdruck wird erst zur Laufzeit bekannt. 2) Die Anzahl variabel und ihre Werte werden erst zur Laufzeit bekannt. 3) Variablenwerte sind nie null.

Ich weiß, dass ich ein einfache mit einer Klasse zusammenstellen schaffen könnte, und ein Verfahren, das ich zur Laufzeit erzeugen an den Eingängen basieren, aber gibt es einen besseren Weg. Ich habe das schon mal gemacht. Verwenden Sie einen String-Builder, um den Code zu schreiben, dann rufen Sie den Compiler. Danach werden Sie die Assembly laden und die Methode aufrufen.

Verbesserungsvorschläge?

Danke.

War es hilfreich?

Lösung

Wenn Sie mit NET3.5 dann können Sie den Text analysieren und erstellen einen abstrakten sytax Baum, um die Expression-Klassen. Dann erstellen Sie eine geeignete Instanz Lambda und kompilieren sie in einen Delegierten, die Sie dann ausführen kann.

einen Parser und Syntax Tree-Builder für diese Art von ziemlich einfach grammer Constructing ist eine ganz interessante Übung, und führen Sie etwas schneller als das Aufrufen der Compiler (und es ist ordentlicheres meiner Meinung nach auch).

Wenn Sie nicht NET3.5 verwenden, dann ist es auch einen interpretierte abstrakter Syntaxbaum zu implementieren selbst nicht kompliziert.

Andere Tipps

Seien Sie gewarnt: Die beiden Endbedingungen Sie sprechen nicht unbedingt gleichwertig. Die && Operatoren in C # wird Kurzschluss evalution verwenden, während der logische And Operator in VB nicht. Wenn Sie die Anweisungen sind gleichwertig sicher sein wollen, übersetzen einen Benutzer And AndAlso und einen Benutzer Or OrElse.

Für einfache Expresssions Sie wahrscheinlich keinen Unterschied bemerken. Aber wenn die Bedingungen können Nebenwirkungen haben, oder wenn der Leistungsunterschied zwischen den beiden ein Anliegen ist, kann dies wichtig sein.

Sie können dies einfach mit:

  1. a Parser-Generator (wie ANTLR, wie oben erwähnt), die Boolesche Ausdrücke als Eingabe und erzeugt eine Liste Infix und
  2. Code, um einen Reverse Polish Notation Stapel zu bewerten.

Die Grammatik sieht ungefähr wie folgt aus:

program: exprList ;

exprList: expr { Append($1); }
    | expr OR exprList { Append(OR); }
    | expr AND exprList { Append(AND); }
    | NOT exprList { Append(NOT); }
    | ( exprList ) { /* Do nothing */ }
    ;

expr: var { Append($1); }
    | TRUE { Append(True); }
    | FALSE { Append(False); }
    ;

Um zu bewerten, können Sie dies tun:

for each item in list
    if item is symbol or truth value, push onto RPN stack
    else if item is AND, push (pop() AND pop())
    else if item is OR, push (pop() OR pop())
    else if item is NOT, push (NOT pop())

result = pop()

Für Symbole, haben Sie den Wahrheitswert zur Laufzeit ersetzen.

Sie können mit https://github.com/mrazekv/logicalparser

Es ist einfach Bibliothek logischen Ausdruck schreiben (mit precenednce Tabelle evaulated, ermöglicht OR, NOT, AND-Operator und>,> =, <=,

Sie können einen einfachen Interpreter / Parser schreiben. Verwenden Sie so etwas wie ANTLR und Wiederverwendung bestehender Grammatiken.

Wenn Sie .NET 3.5 verwenden, können Sie einen Lambda-Ausdruck erstellen. Dann können Sie einen Delegierten von ihm und rufen als Standard delegieren / Methode erstellen. Auf dem Internet ist eine Menge von Proben über Lambda-Ausdrücke.

Eine Lösung wäre, den Ausdruck als String zu montieren und dann SQL Server senden, oder was auch immer Ihre Datenbank ist für die Bewertung. Ersetzen Sie die tatsächlichen Variablen mit 1 = 1 oder 0 = 1 für Wahr und Falsch sind, und Sie würden mit einer Abfrage am Ende wie folgt:

SELECT 1 WHERE (1 = 1 und 0 = 1) oder (1 = 1 und 1 = 1) oder (nicht 0 = 1 und 1 = 1)

Dann, wenn Sie die Abfrage ausführen, erhalten Sie eine 1 zurück, wenn das Ergebnis stimmt. Vielleicht nicht die eleganteste Lösung, aber es wird funktionieren. Eine Menge Leute werden wahrscheinlich abraten, aber ich bin nur dort ohnehin als eine mögliche Lösung gehen zu werfen.

Dies wird nicht die beste Antwort, aber ich hatte dieses Problem vor einiger Zeit.

Hier ist mein alter Code: VB.Net - keine Garantie auf alle

https://cloud.downfight.de/index.php/s/w92i9Qq1Ia216XB

Dim BoolTermParseObjekt As New BoolTermParse
MsgBox(BoolTermParseObjekt.parseTerm("1 und (((0 oder 1 und (0 oder 4))) oder 2)").ToString)

Dieser Code isst einen String mit mehreren ‚(‘, ‚)‘, ‚und‘, ‚oder‘ Plus ‚andere Dinge‘ und bricht die Logik zu einem boolean nach unten, indem sie die Dinge mit Boolesche Werte zu ersetzen. daher:

Wie auch immer ‚andere Dinge‘ wollte ich, dass ich bewerten hatte in Funktion resolveTerm setzen () bei dem Kommentar "'Funktionen ausführen und zurückgeben, einzelwert!" in Seite 2. Dort ist die einzige Auswertung rightnow ist „Wenn Zahl> 1“

Grüße

Werfen Sie einen Blick auf meine Bibliothek, Proviant . Es ist eine .NET-Standard-Bibliothek mit dem Rangierbahnhof Algorithmus Booleschen Ausdrücken zu bewerten.

Es könnte auch eine Wahrheitstabelle für Ihre Ausdrücke erzeugen.

Sie können auch Ihre eigene Grammatik implementieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top