【问题标题】:Evaluate multiple conditions stored as a string评估存储为字符串的多个条件
【发布时间】:2013-06-30 07:45:51
【问题描述】:

我在数据库中存储了一些字符串,其中包含必须满足的特定规则。规则是这样的:

>25
>25 and < 82
even and > 100
even and > 10 or odd and < 21

给定一个数字和一个字符串,在 PHP 中评估它的最佳方法是什么?

例如。给定数字 3 和字符串“偶数和 > 10 或奇数和

谢谢

米奇

【问题讨论】:

  • 我一直在研究 eval() 和一些正则表达式,但似乎没有什么能完全符合我的要求。我试图避免进行大量比较。即如果 str[0] == ">" 那么 ...
  • 您的问题没有通用的解决方案。它可以很复杂也可以很简单。 (我会尽量保持简单)。不过,你可以看看 php parser generator 和 lexer packages,教程:blog.oncode.info/2007/10/25/…(德语,但看代码应该是一个起点)

标签: php string evaluation


【解决方案1】:

如 cmets 中所述,解决此问题的方法可能非常简单,也可能非常复杂。

我整理了一个函数,可以与您给出的示例一起使用:

function ruleToExpression($rule) {
    $pattern = '/^( +(and|or) +(even|odd|[<>]=? *[0-9]+))+$/';
    if (!preg_match($pattern, ' and ' . $rule)) {
        throw new Exception('Invalid expression');
    }
    $find = array('even', 'odd', 'and', 'or');
    $replace = array('%2==0', '%2==1', ') && ($x', ')) || (($x');
    return '(($x' . str_replace($find, $replace, $rule) . '))';
}

function evaluateExpr($expr, $val) {
    $x = $val;
    return eval("return ({$expr});");
}

这支持由andor 分隔的多个子句,没有括号并且总是首先评估and。每个子句可以是 evenodd 或与数字的比较,允许对 &gt;&lt;&gt;=&lt;= 进行比较。

它通过将整个规则与正则表达式模式进行比较来确保其语法有效且受支持。如果它通过了该测试,那么随后的字符串替换将成功地将其转换为针对变量 $x 硬编码的可执行表达式。

举个例子:

ruleToExpression('>25');
// (($x>25))

ruleToExpression('>25 and < 82');
// (($x>25 ) && ($x < 82))

ruleToExpression('even and > 100');
// (($x%2==0 ) && ($x > 100))

ruleToExpression('even and > 10 or odd and < 21');
// (($x%2==0 ) && ($x > 10 )) || (($x %2==1 ) && ($x < 21))

evaluateExpr(ruleToExpression('even and >25'), 31);
// false

evaluateExpr(ruleToExpression('even and >25'), 32);
// true

evaluateExpr(ruleToExpression('even and > 10 or odd and < 21'), 3);
// true

【讨论】:

    【解决方案2】:

    为什么不将字符串even 翻译成数学?如果您使用模组,您可以像$number % 2 == 0 那样编写它。在这种情况下,您的示例将是:

    if(($number % 2 == 0 && $number > 10 ) || ($number % 2 != 0 && $number < 21)){
    //Then it is true!
    }
    

    【讨论】:

    • 我知道如何使用mods,但是如何生成上面的php代码只给一个字符串?
    猜你喜欢
    • 1970-01-01
    • 2019-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-21
    • 1970-01-01
    • 2022-01-02
    相关资源
    最近更新 更多