Drools规则改写:如何遍历平均分列表判断全量条件并修正执行逻辑
问题描述
现有如下Drools规则,用于检查学生是否至少拥有2门成绩,且所有学科平均分不低于5:
rule "student with an average of 5 per discipline and at least two grades" salience 7 when $student : Student(grades.size() >= 2) $list : Object() from computeAverageGrade($student) $value : Double() from $list Boolean(booleanValue() == true) from $value >= 5.0 then System.out.println(3); student.setValid(true); end rule "student with at least two grades and average less than 5" salience 8 when $student : Student(grades.size() >= 2) $list : Object() from computeAverageGrade($student) $value : Double() from $list Boolean(booleanValue() == true) from $value < 5.0 then System.out.println(2); student.setValid(false); end
当前规则会对computeAverageGrade返回的平均分列表中每个元素单独触发,导致当学生平均分列表为[2.0, 9.5, 10.0, 4.5]时,规则输出2 2 3 3,不符合预期。需要改写规则,使得只要存在任意一门学科平均分低于5,就仅执行第二条规则;若所有学科平均分均不低于5,则执行第一条规则。
解决方案
可以利用Drools的every和exists关键字实现集合级别的判断,避免遍历每个元素重复触发规则:
// 规则1:所有学科平均分≥5且至少2门成绩 rule "all averages >=5 and at least two grades" salience 7 when $student : Student(grades.size() >= 2) $averages : List() from computeAverageGrade($student) // 确保列表中所有平均分都≥5 every $avg : Double() from $averages where ($avg >= 5.0) then System.out.println(3); $student.setValid(true); end // 规则2:存在学科平均分<5且至少2门成绩 rule "any average <5 and at least two grades" salience 8 when $student : Student(grades.size() >= 2) $averages : List() from computeAverageGrade($student) // 检查列表中是否存在至少一个平均分<5 exists Double(doubleValue() < 5.0) from $averages then System.out.println(2); $student.setValid(false); end
关键改动说明
- 集合级判断:用
every确保所有平均分都满足≥5的条件,用exists检查是否存在低于5的平均分,每个学生只会触发一次对应规则,不会重复执行。 - 变量修正:原规则中
then块的student未绑定,改为使用绑定的$student变量,避免运行错误。 - 优先级保持:保留原规则的
salience设置,确保“存在低分”的规则优先级更高,逻辑上两个规则不会同时触发,因为一个学生不可能同时满足“所有平均分≥5”和“存在平均分<5”。
内容的提问来源于stack exchange,提问作者Ștefan Jiroveanu
相关产品推荐
相关产品推荐

