【问题标题】:Comparing a list/set of objects efficiently有效地比较一个列表/一组对象
【发布时间】:2017-06-14 21:15:35
【问题描述】:

我正在尝试比较两个 Fact 数据结构。

每个Fact 都由一个谓词和一个参数列表组成

private String predicate;
private ArrayList<Argument> arguments;

Argument 类由一个变量和一个符号组成

String variable;
argTypes symbol;

public enum argTypes {
    STRING, EQ, GT, LT, MATCHONE, MATCHALL, VAR
}

有两个子类numericArgumentstringArgument

private boolean isNeg;
private int value; //or private String value if stringArgument

数字参数示例:length = 10, length != 10, length &gt; 10, length &lt; 10

字符串参数示例:length = long, length != long

arguments 的值也可能为 ?(仅匹配一个参数)、*(匹配 0 个或多个参数)、&amp;x(变量) - 我将它们构造为通用 Argument 类型,设置他们适当的symbol 字段

那么就开始匹配吧!好的匹配示例:

cat(height = tall, colour = black, length=30)cat(height = tall, colour = black, length&gt;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 代替参数数组列表。我还尝试将containsMatchAll 字段添加到Fact,而不是在参数列表中包含*

我将非常感谢有关如何彻底检查此数据结构以使匹配不会超慢的建议。

谢谢!

【问题讨论】:

  • 您如何比较:cat(height = tall, colour = black, length&gt;20)cat(height = tall, colour = black, length&gt;30)
  • @alfasin 不匹配!
  • 这意味着你的“比较”不是传递的,因为它们都匹配:cat(height = tall, colour = black, length=40)。由于比较不具有传递性(您不能应用线性顺序),因此问题与仅仅找出正确的数据结构完全不同。
  • 哦,有趣! Tbh,从给出的规格来看,事情还很不清楚。假设比较确实是传递性的,请问您有什么建议?
  • 但你刚才说它不是传递的......

标签: java list oop set software-design


【解决方案1】:

你可以考虑转换

private ArrayList<Argument> arguments;

进入地图,说

private HashMap<String, Argument> arguments;

其中,映射中的每个条目都是一个键:值对,由参数/变量名称和作为参数引用的值组成。

然后,当比较两个不同对象的 Arguments 时,您可以迭代第一个对象的 Argument map 的键:

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
        }
    }
}

这有一个额外的好处,您可以防止对象包含具有相同名称的重复变量。

这实际上是您(程序员)应该做出的设计决定。我应该添加一个免责声明,这不是解决此问题的唯一方法,这只是其中之一,但对于您要执行的操作来说是一种方便的方法。

【讨论】:

  • 谢谢,这似乎是一个可能的解决方案。然而,虽然永远不会有重复的 Argument 对象,但完全有可能存在多个具有相同变量名的参数,即 height &lt; 10height &gt; 5,所以我不太确定 hashmap 是否适合我案子。您还介意建议我应该如何处理?(匹配一个变量)和*(匹配≥0 个变量)通配符吗?在最后一个 q 上也很感谢您的意见@alfasin
  • @joelross 好的,我明白了。在这种情况下,您可以使用 map>。否则,作为 Pure ArrayLists,您将具有二次运行时复杂性。此外,您可以考虑为同一事物添加通配符类。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-17
  • 2018-01-20
  • 2018-06-07
  • 1970-01-01
  • 1970-01-01
  • 2016-11-17
  • 1970-01-01
相关资源
最近更新 更多