有效地比较 list/set 个对象
Comparing a list/set of objects efficiently
我正在尝试比较两个 Fact
数据结构。
每个 Fact
由一个谓词和一个参数列表组成
private String predicate;
private ArrayList<Argument> arguments;
Argument
class由一个变量和一个符号组成
String variable;
argTypes symbol;
public enum argTypes {
STRING, EQ, GT, LT, MATCHONE, MATCHALL, VAR
}
有两个子classes 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
arguments 也可能有值 ?
(只匹配一个参数),*
(匹配 0 个或多个参数),&x
(一个变量)- 我构造这些作为通用参数类型,设置它们适当的 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
而不是在参数列表中包含 *
。
我将非常感谢有关彻底检查此数据结构的方法的建议,以便匹配不会超慢。
谢谢!
您可以考虑转换
private ArrayList<Argument> arguments;
进入地图,说
private HashMap<String, Argument> arguments;
其中,映射中的每个条目都是一个键:值对,由 argument/variable 名称和作为参数引用的值组成。
然后,当比较两个不同对象的 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
}
}
}
这有额外的好处,您可以防止对象包含具有相同名称的重复变量。
这实际上是您作为程序员应该做出的设计决定。我应该添加一个免责声明,这不是解决这个问题的唯一方法,这只是其中之一,但是对于您要执行的操作来说是一个方便的方法。
我正在尝试比较两个 Fact
数据结构。
每个 Fact
由一个谓词和一个参数列表组成
private String predicate;
private ArrayList<Argument> arguments;
Argument
class由一个变量和一个符号组成
String variable;
argTypes symbol;
public enum argTypes {
STRING, EQ, GT, LT, MATCHONE, MATCHALL, VAR
}
有两个子classes 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
arguments 也可能有值 ?
(只匹配一个参数),*
(匹配 0 个或多个参数),&x
(一个变量)- 我构造这些作为通用参数类型,设置它们适当的 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
而不是在参数列表中包含 *
。
我将非常感谢有关彻底检查此数据结构的方法的建议,以便匹配不会超慢。
谢谢!
您可以考虑转换
private ArrayList<Argument> arguments;
进入地图,说
private HashMap<String, Argument> arguments;
其中,映射中的每个条目都是一个键:值对,由 argument/variable 名称和作为参数引用的值组成。
然后,当比较两个不同对象的 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
}
}
}
这有额外的好处,您可以防止对象包含具有相同名称的重复变量。
这实际上是您作为程序员应该做出的设计决定。我应该添加一个免责声明,这不是解决这个问题的唯一方法,这只是其中之一,但是对于您要执行的操作来说是一个方便的方法。