Pregunta

Lo mejor era evaluar una expresión como la siguiente:
(A y B) o (A y C) o (no B y C)
o
(A && b) || (A && c) || (!ANTES DE CRISTO)

En tiempo de ejecución, estaba planeando convertir las expresiones anteriores a lo siguiente:
(Verdadero y falso) O (Verdadero y falso) O (No falso y verdadero)
o
(True && False) || (True && False) || (!Falso verdadero)

Condiciones:1) La expresión lógica no se conoce hasta el tiempo de ejecución.2) La variable numérica y sus valores no se conocen hasta el tiempo de ejecución.3) Los valores de las variables nunca son nulos.

Sé que podría crear un ensamblado simple con una clase y un método que genero en tiempo de ejecución en función de las entradas, pero ¿existe una manera mejor?He hecho esto antes.Utilice un generador de cadenas para escribir el código y luego llame al compilador.Después de eso, carga el ensamblaje y llama al método.

¿Sugerencias?

Gracias.

¿Fue útil?

Solución

Si está usando .NET3.5, entonces puede analizar el texto y crear un árbol de sintaxis abstracta usando las clases de Expresión. Luego cree una instancia de LambdaExpression adecuada y compílela en un delegado, que luego puede ejecutar.

Construir un analizador sintáctico y un generador de árbol de sintaxis para este tipo de gramática bastante simple es un ejercicio bastante interesante, y se ejecutará algo más rápido que invocar el compilador (y en mi opinión también es más ordenado).

Si no está utilizando .NET3.5, tampoco es complicado implementar un árbol de sintaxis abstracta interpretada.

Otros consejos

Tenga cuidado:Las dos condiciones finales de las que estás hablando no son necesariamente equivalentes.Los operadores && en C# utilizarán evaluación de cortocircuito, mientras que los operadores lógicos And El operador en VB no lo hace.Si quieres estar seguro de que las declaraciones son equivalentes, traduce un usuario And a AndAlso y un usuario Or a OrElse.

Para expresiones simples probablemente no notarás la diferencia.Pero si las condiciones pueden tener efectos secundarios o si la diferencia de rendimiento entre ambas es motivo de preocupación, esto puede ser importante.

Puede hacerlo fácilmente con:

  1. un generador de analizador (como ANTLR, mencionado anteriormente) que toma expresiones booleanas como entrada y produce una lista infija y
  2. código para evaluar una pila de notación polaca inversa.

La gramática se parece a esto:

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); }
    ;

Para evaluar, debe hacer esto:

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()

Para los símbolos, debe sustituir el valor de verdad en tiempo de ejecución.

Puede usar https://github.com/mrazekv/logicalparser

Su biblioteca simple para escribir expresiones lógicas (evacuadas con tabla de precedencia, permite operador OR, NOT, AND y > ;, > =, < =, < en variables enteras y = en variables de cadena)

Puede escribir un intérprete / analizador simple. Use algo como ANTLR y reutilice las gramáticas existentes.

Si está utilizando .NET 3.5, puede crear una Expresión Lambda. Luego puede crear un delegado a partir de él y llamar como delegado / método estándar. En Internet hay muchas muestras sobre las expresiones Lambda.

Una solución sería ensamblar la expresión como una cadena y luego enviarle SQL Server, o lo que sea que su base de datos sea para evaluación. Reemplace las variables reales con 1 = 1 o 0 = 1 para Verdadero y Falso respectivamente, y terminaría con una consulta como esta:

SELECCIONE 1 DONDE (1 = 1 y 0 = 1) o (1 = 1 y 1 = 1) o (no 0 = 1 y 1 = 1)

Luego, cuando ejecuta la consulta, obtiene un 1 cuando el resultado es verdadero. Puede que no sea la solución más elegante, pero funcionará. Mucha gente probablemente desaconsejará esto, pero de todos modos lo voy a lanzar como una posible solución.

Esta no será la mejor respuesta, pero yo mismo tuve este problema hace algún tiempo.

Aquí está mi código anterior: VB.Net: ¡ninguna garantía!

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)

Este código come una cadena con múltiples '(', ')', 'y', 'o' más 'otras cosas' y descompone la lógica en booleana al reemplazar las cosas con valores booleanos. por lo tanto:

Cualquier 'otra cosa' que quisiera evaluar tuve que ponerla en Function resolveTerm () en el comentario " 'funktionen ausf & # 252; hren und zur & # 252; ckgeben, einzelwert! " en la página 2. Allí la única evaluación correcta es & Quot; Si el número es & Gt; 1 & Quot;

Saludos

Eche un vistazo a mi biblioteca, Proviant . Es una biblioteca .NET Standard que utiliza el algoritmo Shunting Yard para evaluar expresiones booleanas.

También podría generar una tabla de verdad para sus expresiones.

También podría implementar su propia gramática.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top