比方说,我有红色和绿色的篮子,里面装有盒草莓和葡萄:
public class Basket {
public enum Color { RED, GREEN };
private Color color;
private List<FruitBox> fruitBoxes;
//Assume appropriate constructors, getters exist
}
public class FruitBox {
public enum Fruit { STRAWBERRY, GRAPE };
private Fruit fruit;
//Assume appropriate constructors, getters exist
}
我需要使用Drools来打印以下计算:
我该如何按照简单高效的Drools规则编码(1.)和(2.)?阅读文档后,我提出了以下解决方案:
rule "Two or more of same fruit in any Basket"
when
//Bind the contents of each basket
$Basket : Basket($FruitBoxes : fruitBoxes)
//Compute A list of the unique fruits in current basket contents
$fruits : Object() from accumulate( FruitBox($f : fruit) from $FruitBoxes, collectSet($f) )
//Match and bind each unique fruit one by one
$fruit : FruitBox.Fruit() from $fruits
//Find the number of times the unique fruit occurs in this Basket
$count : Number(intValue >= 2) from accumulate(
$f : FruitBox(fruit == $fruit) from $FruitBoxes,
count($f) )
then
System.out.println($Basket + " has " + $count + " of the fruit " + $fruit);
end
对于一个测试数据集,成功打印出的输出如下:
com.sample.DroolsTest$Basket@10cd6753 has 4 of the fruit STRAWBERRY
com.sample.DroolsTest$Basket@10cd6753 has 3 of the fruit GRAPE
com.sample.DroolsTest$Basket@2e060819 has 2 of the fruit GRAPE
我担心的是,我的规则漫长而复杂,并且似乎对每个篮子进行了多次迭代(一旦在其中找到独特的水果,然后再对每个水果进行计数)。我怀疑这是我缺乏Drools知识的产物,并且存在更好的解决方案。在纯Java中,我将使用HashMap一次存储每个水果及其数量,这既简单又快速。有什么方法可以重写我的Drools代码以提高性能和可读性?同样的问题也适用于我的第二条规则:
rule "Totals by fruit and by basket color"
when
//Calculate the cross product of all fruits and colors
$fruit : FruitBox.Fruit()
$color : Basket.Color()
//Count the number of FruitBoxes of the chosen fruit in Baskets of the chosen color
$count : Number() from accumulate(
$fb : FruitBox(fruit == $fruit)
and exists Basket(color == $color, fruitBoxes contains $fb),
count($fb) )
then
System.out.println($count + " " + $fruit + " in " + $color + " baskets");
end
哪个会产生如下输出:
5 STRAWBERRY in GREEN baskets
6 STRAWBERRY in RED baskets
6 GRAPE in GREEN baskets
4 GRAPE in RED baskets
但是,不幸的是,看起来它在每个FruitBox的所有篮子中搜索,而在一次遍历篮子的同时计算一个(或全部)种类的FruitBox会更有意义。就性能而言,此规则是否有更好的语法?
感谢您的帮助!
答案 0 :(得分:0)
嗨,第一个问题,我将使用两个单独的规则:
rule "strawberriesInBasket"
dialect "mvel"
when
$basket : Basket($fruitBoxes : fruitBoxes)
Number($count : intValue() > 2) from accumulate ($fruitBox : FruitBox(fruit.name == "strawberry") from $fruitBoxes, count($fruitBox))
then
System.out.println("Count of strawberry boxes in basket is: " + $count )
end
和
rule "grapesInBasket"
dialect "mvel"
when
$basket : Basket($fruitBoxes : fruitBoxes)
Number($count : intValue() > 2) from accumulate ($fruitBox : FruitBox(fruit.name == "grape") from $fruitBoxes, count($fruitBox))
then
System.out.println("Count of grape boxes in basket is: " + $count )
end
请注意,我已将枚举水果更改为具有字段名称的数据对象。