考虑以下场景,其中ID定义的规则需要满足所有条件。
规则ID属性1操作员1值1属性2操作员2值1。。。等等-------------------------------------------------------------------1 x=10 a IN 5,102 x=20 a IN 10,153 x=20 a IN 25,20
以上表示if(x=10) & if(a = 5 or a = 10} & ..., then ID = 1
在格式为[x, a, ...]
的传入馈送的情况下
10,5。。。10,10。。。20,20
则ID应为
11.3
我想检查是否有比下面的解决方案更简单、更优雅的方法,以及要使用哪种数据结构
数据结构的缺点是什么;以下解决方案中使用的方法?(肯定会有)
Assumptions:
- 属性列表目前已固定,但可能会更改
- 传入的提要格式是固定的
- 不在Java规则实现的线上
- 算法答案是可以接受的,Java 7实现是首选
我的解决方案:
-
规则集组织为
Map<String, List<Criterion>>
,其中key是ID,Criterion包含属性、运算符和值作为字段。 -
数据被组织为
List<Map<String, String>>
,其中key是属性(可以是x或a等),value是提要中的实际值。 -
对于
List<Map<String, String>
中的每个条目,请执行以下操作以查找ID -
循环遍历
Map<String, List<Criterion>>
中的每个条目,并调用以下方法。在返回true
的情况下,我记录ID,这是密钥,并打破规则循环&进入下一个数据项。public boolean executeRules(List<Criterion> list, Map<String, String> dataItem) { boolean fullMatch = true; if(CollectionUtils.isNotEmpty(list)){ for(Criterion rule : list) { switch (rule.getOperator()) { case EQUAL_TO: //Similar to EQUAL TO if(!rule.getValue().equals(dataItem.get(rule.getOperand()))){ fullMatch = false; } break; case IN://Similar to IN List<String> inCriteria = null; if(rule.getValue() != null) { inCriteria = Arrays.asList(((String) rule.getValue()).split("\s*,\s*")); if(!inCriteria.contains(dataItem.get(rule.getOperand()))){ fullMatch = false; } } else { fullMatch = false; } break; default: LOG.error("Invalid Operator: " + rule.getOperator()); fullMatch = false; break; } if(!fullMatch) { return false; } } } else { LOG.error("No Rules found"); return false; } return true; }
PS:不是家庭作业;只是一些研究。
我认为您可以使用SmartParam库(http://smartparam.org/)。它是为此类评估而设计的,并且非常通用,因此即使与属性文件以及数据库一起使用,也可以使用if