我正在尝试比较两个Fact
数据结构。
每个Fact
由谓词和参数列表组成
private String predicate;
private ArrayList<Argument> arguments;
Argument
类由变量和符号
String variable;
argTypes symbol;
public enum argTypes {
STRING, EQ, GT, LT, MATCHONE, MATCHALL, VAR
}
有两个子类numericArgument
和stringArgument
private boolean isNeg;
private int value; //or private String value if stringArgument
数字参数示例:length = 10, length != 10, length > 10, length < 10
字符串参数示例:length = long, length != long
参数也可能具有?
的值(仅与一个参数匹配),*
(匹配0或更多参数),&x
(变量) - 我将这些构造为通用的Argument类型,设置适当的symbol
字段
所以进入匹配!良好匹配的例子:
带有cat(height = tall, colour = black, length=30)
的 cat(height = tall, colour = black, length>20)
cat(black)
cat(!brown)
Cat(fur = soft, colour = brown, size = 10)
匹配Cat(fur = soft, *)
不良比赛的例子:
带有Cat(fur = soft, colour = brown, size = 10)
的 Cat(fur = soft, colour = brown)
[缺少的参数完全定义了不同的谓词]
我已经实现了匹配两个Argument
对象的方法,但我正在努力实现比较两个Fact
对象的好方法。我已经尝试使用Hashset和LinkedHashSet而不是参数arraylist。我还尝试向containsMatchAll
添加Fact
字段,而不是在参数列表中包含*
。
我非常感谢有关如何彻底检查此数据结构的建议,以便匹配不会超级慢。
谢谢!
答案 0 :(得分:0)
您可以考虑转换
private ArrayList<Argument> arguments;
进入地图,说
private HashMap<String, Argument> arguments;
其中,映射中的每个条目都是一个键:值对,由参数/变量名称和值为参数引用组成。
然后,在比较两个不同对象的Arguments时,您可以迭代第一个对象的Argument映射的键:
if (object1.getArguments().size() != object2.getArguments.size()) {
... // they don't even have the same number of arguments, this is the first check
} else {
for(String variableName : object1.getArguments().keySet()) {
if(!object2.getArguments().contains(variableName)) {
... // bad match !
break;
} else {
Argument arg1 = object1.getArguments().get(variableName);
Argument arg2 = object2.getArguments().get(variableName);
... // do some comparison here
}
}
}
这可以防止对象包含具有相同名称的重复变量。
这实际上是程序员应该采取的设计决策。我应该添加一个免责声明,这不是解决此问题的唯一方法,这只是其中之一,但对于您要执行的操作来说非常方便。