为什么“来自”关键字向后迭代?

发布于 2024-10-13 10:09:27 字数 878 浏览 4 评论 0原文

我的工作内存中有一个 ArrayList,我正在 when 子句中使用“from”语句进行迭代。然而,该规则是向后迭代数组。有没有办法控制这种行为?

列表创建:

List<Map<String,String>> list = new ArrayList<Map<String,String>>();
Map<String,String> m1 = ...
Map<String,String> m2 = ...
list.add(m1);
list.add(m2);
ImportItem item = new ImportItem(list);  //model object. Constructor arg returned by getInput()
StatelessKnowledgeSession session = knowledgeBase.newStatelessKnowledgeSession();
session.insert(item);
session.fireAllRules();

Drools 规则:

rule "My Rule"
dialect "java"
when
    item : ImportItem(ignore == false)  //model object that holds the input
    map  : Map() from item.getInput()  // == the ArrayList from above
then
    System.out.println(map);
end

产品

<output of m2>
<output of m1>

I have an ArrayList in working memory that I am iterating with a 'from' statement in my when clause. However, the rule is iterating backwards through the array. Is there a way to control this behavior?

List Creation:

List<Map<String,String>> list = new ArrayList<Map<String,String>>();
Map<String,String> m1 = ...
Map<String,String> m2 = ...
list.add(m1);
list.add(m2);
ImportItem item = new ImportItem(list);  //model object. Constructor arg returned by getInput()
StatelessKnowledgeSession session = knowledgeBase.newStatelessKnowledgeSession();
session.insert(item);
session.fireAllRules();

Drools rules:

rule "My Rule"
dialect "java"
when
    item : ImportItem(ignore == false)  //model object that holds the input
    map  : Map() from item.getInput()  // == the ArrayList from above
then
    System.out.println(map);
end

Produces

<output of m2>
<output of m1>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

謌踐踏愛綪 2024-10-20 10:09:27

迭代不是向后的,正如您在会话中附加审核日志时可以看到的那样。默认情况下,规则的执行遵循 LIFO 顺序(如果您不使用任何其他冲突解决策略)。

我对您的建议是不要尝试将对象封装在数据结构中。如果您正在读取文件的行并且需要按顺序处理这些行,只需使用一个类来表示该行并将这些行直接插入到会话中即可。为了保证执行顺序,可以使用行号作为显着性参数。

例如:

rule "Process lines in order"
   // salience executes from higher number to lowest number, so using the 
   // negative value you will executem them from the first to the last
   salience (- $lineNumber )
when
   $line : Line( $lineNumber : lineNumber )
then
   // do something with $line
end

显然,相同的技巧可以用于您采用的“from”方法,但引擎在工作内存中匹配事实比迭代对象集合要有效得多。

希望有帮助。
埃德森

The iteration is not backwards, as you can see if you attach an audit log to your session. The execution of the rules is what follows, by default, a LIFO order (in case you are not using any other conflict resolution strategy).

My suggestion for you is don't try to encapsulate the objects in data structures. If you are reading lines of a file and you need to process these lines in order, just use a class to represent the line and insert the lines directly into the session. To guarantee execution order, you can use the line number as a parameter to salience.

For instance:

rule "Process lines in order"
   // salience executes from higher number to lowest number, so using the 
   // negative value you will executem them from the first to the last
   salience (- $lineNumber )
when
   $line : Line( $lineNumber : lineNumber )
then
   // do something with $line
end

Obviously the same trick can be used with the "from" approach you took, but the engine is much more efficient matching facts in the working memory than it is iterating over collections of objects.

Hope it helps.
Edson

夏了南城 2024-10-20 10:09:27

您应该始终尝试编写规则,以便顺序不重要。但是,如果您确实需要按特定顺序触发规则,或者在这种情况下,按特定顺序从列表中获取事实。确保当您更新到较新版本的引擎时,规则引擎内部的任何更改都不会破坏您的规则。

你不能相信“来自”,即使它以相反的方式进行迭代。

该解决方案有一个问题。如果更新 ImportItem 并需要再次迭代输入,则需要收回与其相关的 MyIterator。

declare MyIterator
    index:int
    lastIndex:int
    importItem:ImportItem
end 

rule "Insert ImportItem iterator"
    when
        item : ImportItem()
        not MyIterator( importItem == item )
    then
        MyIterator myIterator = new MyIterator();
        myIterator.setImportItem( item );
        myIterator.setIndex( 0 );
        myIterator.setLastIndex( item.getInput().size() ); 
        insert( myIterator );
end

rule "My Rule"
    when
        myIterator :MyIterator( index < lastIndex )
        item : ImportItem(  this == myIterator.importItem, 
                            ignore == false )
        map  : Map() from item.getInput().get( myIterator.getIndex() )  
    then
        System.out.println(map);

        myIterator.setIndex( myIterator.getIndex() + 1 );
        update( myIterator );
end

You should always try to write the rules so that the order doesn't count. If however, you really really need to have rules firing in certain order, or in this case, get the facts from a list in a certain order. Make sure that whatever changes in the rule engine internals doesn't break up your rules when you update to a newer version of the engine.

You can't trust the "from" even if it did the iteration the other way around.

There is one problem with this solution. If you update the ImportItem and need to iterate through the input again, you need to retract the MyIterator that is related to it.

declare MyIterator
    index:int
    lastIndex:int
    importItem:ImportItem
end 

rule "Insert ImportItem iterator"
    when
        item : ImportItem()
        not MyIterator( importItem == item )
    then
        MyIterator myIterator = new MyIterator();
        myIterator.setImportItem( item );
        myIterator.setIndex( 0 );
        myIterator.setLastIndex( item.getInput().size() ); 
        insert( myIterator );
end

rule "My Rule"
    when
        myIterator :MyIterator( index < lastIndex )
        item : ImportItem(  this == myIterator.importItem, 
                            ignore == false )
        map  : Map() from item.getInput().get( myIterator.getIndex() )  
    then
        System.out.println(map);

        myIterator.setIndex( myIterator.getIndex() + 1 );
        update( myIterator );
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文