问题
My requirement is to match tags. In the example, this particular HourConstraint
checks the TeacherHour
assigned to Hour(23)
.
Specifically, it checks TeacherHour.attributes["tags"]
for the values ["asst_ct","teacher_john_smith"]
and detects atleast one match, two in this case (both "asst_ct"
and "teacher_john_smith"
) .
TeacherHour:
id: 47
assigned_hour: Null
attributes:Map<List<String>>
"tags":["asst_ct","no_strenuous_duties","kinda_boring","teacher_john_smith"]
"another_attribute":[...]
HourConstraint:
hour: Hour(23)
attribute: "tags"
values_list: ["asst_ct","teacher_john_smith"]
Question: How do I detect the presence (true or false) of common elements between two lists?
Drools Expert has memberOf
and contains
, but they check a scalar vs a collection, never a collection vs a collection.
I see two potential ways:
- introduce a function
boolean isIntersecting(list,list)
and tell Drools to use that for truth checking - Implement
TeacherHour.attributes[]
as a string instead of a list andHourConstraint.valueslist
as a regular expression that can match that list
回答1:
There are a few options. Most straight forward is to use the Collections class to do that for you:
rule X
when
$t: TeacherHour( )
HourConstraint( Collections.disjoint( $t.attributes["tags"], values_list ) == false )
...
If this is something you would use often in your rules, then I recommend wrapping that function in a pluggable operator, supported by Drools. Lets say you name the operator "intersect", you can then write your rules like this:
rule X
when
$t: TeacherHour( )
HourConstraint( values_list intersect $t.attributes["tags"] )
...
A third option, is to use "from", but that is less efficient in runtime as it causes iterations on the first list:
rule X
when
$t: TeacherHour( )
$tag : String() from $t.attributes["tags"]
exists( HourConstraint( values_list contains $tag ) )
...
来源:https://stackoverflow.com/questions/9238681/matching-a-list-of-tags-with-another-and-detecting-presence-of-common-elements