【问题标题】:VB.NET: Check if List items are equal and have same countVB.NET:检查列表项是否相等且计数相同
【发布时间】:2013-07-22 12:26:25
【问题描述】:

如何检测两个给定列表的项目是否相等?

Dim list1 As New List(Of Integer)
list1.AddRange({1, 2, 3})

Dim list2 As New List(Of Integer)
list2.AddRange({3, 2, 1})

如果我使用SequenceEqual 比较它们,我会得到False,因为项目的顺序不一样。但是,我如何先对它们进行比较而不对它们进行排序

编辑:请注意这应该尊重重复项,例如 {1, 2, 3, 1}{1, 2, 3} 不同(项目 1 在第一个列表中出现两次)。

【问题讨论】:

  • 循环遍历其中一个列表并检查另一个列表是否包含该元素。还要检查列表的长度是否相同。
  • 为什么先“不排序”?听起来是个不错的选择。
  • @SysDragon:听起来不错,是的,但是如果您想保留列表中的顺序怎么办?但这导致我最终实现了 :-)

标签: vb.net list generics comparison


【解决方案1】:

如果您想知道两个列表是否包含相同的项目,您可以使用Enumerable.Except

Dim bothContainSameItems As Boolean
If list1.Count > list2.Count Then
    bothContainSameItems = Not list1.Except(list2).Any()
Else
    bothContainSameItems = Not list2.Except(list1).Any()
End If

或者,在HashSet(Of T)的帮助下:

Dim l1Set = New HashSet(Of Integer)(list1)
Dim l2Set = New HashSet(Of Integer)(list2)
bothContainSameItems = l1Set.SetEquals(l2Set)

请注意,这两种方法都会忽略重复项。所以他们会返回equal

list1.AddRange({1, 1, 2, 3})
list2.AddRange({3, 2, 1, 3})

还有一种方法可以检查两个列表中的所有数字是否具有相同的计数:

bothContainSameItems = list1.Count = list2.Count
If bothContainSameItems Then
    Dim l1Ordered = list1.OrderBy(Function(i) i).ToList()
    Dim l2Ordered = list2.OrderBy(Function(i) i).ToList()
    For i As Int32 = 0 To l1Ordered.Count - 1
        If l1Ordered(i) <> l2Ordered(i) Then
            bothContainSameItems = False
            Exit For
        End If
    Next
End If

【讨论】:

  • 反例:list1={1,1,2,3}, list2={1,2,3}.
  • @KonradRudolph:我已经添加了一个类似的示例。这取决于他是否要比较集合的要求。
【解决方案2】:

也与

合作
Dim list1 As New List(Of Integer)
list1.AddRange({1, 2, 3})

Dim list2 As New List(Of Integer)
list2.AddRange({3, 2, 1})

Dim list3 = list1.Union(list2)
if list3.OrderBy(Function(i) i).SequenceEqual(list1.OrderBy(Function(i) i)) then
    Console.WriteLine("Equal")
else
    Console.WriteLine("Not Equal")
end if

IEnumerable.Union

返回值:一个 IEnumerable(Of T),包含来自两个输入序列的元素, 排除重复项。

【讨论】:

  • 这会更改第一个列表并且不考虑重复项。
  • @Johannes 我已经说明了工会更改列表的事实。当文档清楚地表明相反时,您为什么认为不考虑重复?至少在投票前检查
  • 文档清楚地说明了这一点。检查此示例:{1,2,3}{1,2,3,1},反之亦然。
  • 文档说:Excluding duplicates' so {1,2,3,4} union {1,2,3,5} returns {1,2,3,4,5}, my error is not writing list3 = list1.Union(list2)` 因为唯一列表是联合的返回值而不是第一个列表。但是,您是对的,这不是您问题的正确答案,因为您仍然无法判断两个列表是否不同(并且计数不是有效的方法)
  • 是的,但是{1,2,3,1}.Union({1,2,3}) 仍然是{1,2,3,1} :)
【解决方案3】:
<System.Runtime.CompilerServices.Extension()> _
Function AreItemsEqual(Of T)(col1 As IEnumerable(Of T), col2 As IEnumerable(Of T)) As Boolean
    ' performance checks
    If col1 Is col2 Then Return True
    If col1 Is Nothing OrElse col2 Is Nothing Then Return False
    If col1.Count <> col2.Count Then Return False
    ' compare their elements
    Dim o1 As IEnumerable(Of T) = col1.OrderBy(Function(i) i)
    Dim o2 As IEnumerable(Of T) = col2.OrderBy(Function(i) i)
    Return o1.SequenceEqual(o2)
End Function

用法:

If list1.AreItemsEqual(list2) Then
    ...

【讨论】:

  • 与我类似的方法:stackoverflow.com/a/17787628/284240 但是,如果集合很大,效率不是很高。
  • SequenceEqual 和我的For-loop 一样,只要条件为False 就会中断。但是,两者都效率低下,因为两个集合都必须复制到一个新集合中,并且两个集合都需要完全排序。
  • 如果两个列表都没有怎么办?
  • 你是对的,前2个检查的顺序需要切换;我更新了函数。
猜你喜欢
  • 1970-01-01
  • 2016-09-13
  • 2017-04-25
  • 1970-01-01
  • 1970-01-01
  • 2012-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多