在Drools的内部集合上累积
假设我有红色和绿色的篮子,里面装着一盒盒草莓和葡萄:在Drools的内部集合上累积,drools,drools-planner,Drools,Drools Planner,假设我有红色和绿色的篮子,里面装着一盒盒草莓和葡萄: public class Basket { public enum Color { RED, GREEN }; private Color color; private List<FruitBox> fruitBoxes; //Assume appropriate constructors, getters exist } public class FruitBox { public
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
}
成功打印一个测试数据集的输出,如:
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
5 STRAWBERRY in GREEN baskets
6 STRAWBERRY in RED baskets
6 GRAPE in GREEN baskets
4 GRAPE in RED baskets
我担心的是,我的规则既长又复杂,似乎要对每个篮子重复几次(一次是为了找到其中唯一的水果,然后再次对每个水果进行计数)。我怀疑这是我缺乏口水知识的结果,还有更好的解决办法。在普通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
产生如下输出:
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
5 STRAWBERRY in GREEN baskets
6 STRAWBERRY in RED baskets
6 GRAPE in GREEN baskets
4 GRAPE in RED baskets
但是,不幸的是,它看起来像是在所有篮子中搜索每个水果盒,而在篮子上迭代一次,将一种(或全部)水果盒汇总起来则更有意义。就性能而言,该规则是否有更好的语法
谢谢你的帮助 您好,对于第一个问题,我将使用两个单独的规则:
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
及
请注意,我将enum水果更改为字段名为的数据对象谢谢,Jomarko!我积累这些结果的原因是上面的代码是一个更大问题的小例子,其中'fruit.name'的值是动态确定的(可能有几百个值)。如果'fruit.name'只有两个值是可能的,那么我同意这将是一个更好的解决方案。好的,我现在更好地理解了。几百个值真是太多了。但是,如果值的域是有限的,我建议您在kie workbench中查看xls决策表或引导决策表。在这两种情况下,您只需编写一次规则(规则的模板),然后将特定规则中不同的值填充到简单表中。