我如何比较VB中的两个列表(<customclass>)?</customclass>

时间:2011-01-16 04:48:18

标签: vb.net list

我正在为我的自定义类实现等于运算符=。该类有一个属性Value,它本身是List(Of OtherClass),其中OtherClass是我项目中的另一个自定义类。

我已经实施了IComparerIComparableIEqualityComparerIEquatable接口,运营商=<>,{ {1}}和bool,并覆盖not的{​​{1}}和Equals。这应该给我比较这些对象所需的所有工具,以及迄今为止比较这些对象的两个单一实例的各种测试。

但是,当我们在GetHashCode时,我不确定如何处理这个问题。我不关心列表顺序。给出:

OtherClass

然后List应打印出Dim x As New List(Of OtherClass) From {New OtherClass("foo"), New OtherClass("bar"), New OtherClass("baz")} Dim y As New List(Of OtherClass) From {New OtherClass("baz"), New OtherClass("foo"), New OtherClass("bar")}

我需要比较此列表中相同(不明显)的对象集。该列表不应该支持(x = y).ToString的欺骗,但我必须弄清楚如何在以后作为例外添加它。对使用LINQ不感兴趣。它看起来不错,但在我玩过的几个例子中,增加了性能开销,这让我感到困扰。循环是丑陋的,但它们很快:)

直接的代码答案很好,但我也想了解这种比较所需的逻辑。我可能不得不在未来几次实施所述逻辑。

2 个答案:

答案 0 :(得分:4)

您的示例应返回false。列表与LT;&GT;是有序集合,如果X包含foo,bar,baz,它与baz,foo,bar不同。你不应该改变这种预期的行为!你描述的是一个集合或包,而不是列表。袋子类似于列表,但不关心物品的顺序。那么在你的例子中它显然会返回true。

为清晰起见编辑:列出&lt;&gt;按项目索引排序,而不是按其值排序。这种收集的这一重要特性影响了它在所有操作中的行为和速度。

好的,忘了它,让我们说你只想按照你的定义进行测试。如果您对内容进行排序然后进行比较,最快的通用应用算法将为O(n * log2n)。 -1。您可以将两个列表排序为两个临时集合,然后只是比较它们的项目。 -2。您可以将X排序为临时集合,然后依次通过Y并尝试在X中查找Y的每个项目并将其删除。最后你可以看到temp是否为空,然后X和Y是相同的。 -3。如果您经常比较相等而不经常插入新项目,则可以创建一些新的“智能”列表,它将在插入时对项目进行排序。它将由一个真正的List&lt;&gt;组成。和里面的某种排序集合。

对复杂性的粗略分析:

选项1.和2.在插入n个项目时为O(n),在比较两个列表时为O(n * log2n)。

选项3.在插入n个项目时为O(n * log2n),在比较两个列表时为O(n)。

如果你想得到O(n * log2n),你可能需要去一个不同于List&lt;&gt;的集合。如果你使用类HashSet(从.NET 3.5开始),你可能会得到更快的结果。但我没有在实践中尝试过。 HashSet是无序集合aka set / bag的实现。它不支持比较两个哈希集,但你可以这样做:

使用foreach迭代X项,并尝试在Y中找到每个项目。

if(X.Count != Y.Count) return false;
foreach(var i in X) {
  if(Y.Contains(i)==false) return false;
}
return true;

此代码在列表上非常慢,它是O(n ^ 2)。但它应该在HashSets上非常快,O(n)。如果你没有遇到任何隐藏的问题,这应该像火箭一样飞行!

在实践中,如果你需要留下List&lt;&gt;并且想要HashSet&lt;&gt;的速度,你可以只将你的一个集合(X或Y)重写为一个新的类,里面将包含两个集合 - 一个List&lt;&gt;和HashSet&lt;&gt; - 并将所有项目存储到他们两个。

您还可以使用经典词典&lt;&gt;,HashTable或其他一些经典的.NET集合来实现相同的功能。它们比比较两个Lits运行得更快,但可能需要更多内存而不是像HashSet一样快。

答案 1 :(得分:-1)

好的Al Kepp我的方法有问题,

        For Each i In CompList1
        Dim indexOfMyItem = CompList1.IndexOf(i)
        If Not (CompList2.Contains(i) = False) Then
            If Not test.ListBox1.Items.Contains(indexOfMyItem) Then
                test.ListBox1.Items.Add(indexOfMyItem)
            End If
        End If
        Next

我有两个列表例如:

CompList1: 0)香蕉 1)苹果 2)苹果 3)苹果 4)草莓 5)樱桃 6)樱桃 7)樱桃 8)猕猴桃

CompList2: 0)苹果 1)樱桃

我需要从list1中的每个匹配中获取索引并将其添加到列表中,由于某些原因我无法弄清楚,我只得到索引1和5,并且没有添加2 3 6 7。

有人能帮助我吗?

编辑:

好吧,这是我对.IndexOf()的误解 - 它只是找到列表中的第一项,其中包含()

中指定的文本

因此我必须按照以下方式正常工作:

    Dim indexOfMyItem As Integer = -1

    For Each i In CompList1
        indexOfMyItem = indexOfMyItem + 1
        If CompList2.Contains(i) Then
            If Not test.ListBox1.Items.Contains(indexOfMyItem) Then
                test.ListBox1.Items.Add(indexOfMyItem)
            End If
        End If
    Next