如何删除两个列表中重复的自定义类条目?

3
奇怪的是这方面的内容不多。
简短版:
ListA有一些ListB也有的元素,而有一些元素则不同。 ListB有一些ListA也有的元素,而有一些元素则不同。实际上,其中绝大部分都是重复的。
注意:这些元素并不是常见类型,而是我自己创建的一个类的类型。(LINQ Intersect似乎只能用于已知类型-请参见下面的更新)
如何删除它们共同拥有的元素?
详细版:
-某个设备上有ListA项目,我想将其与ListB项目同步。我不想删除和新建。那不是一个可行的选择。
-为了同步这些列表,我会:
首先:
  1. (?)删除它们之间的任何重复项(毕竟这些条目已经同步了)。

  2. 第二:(简单)删除剩余的ListA条目(因为它们不在ListB上,否则它们将被视为重复项而被删除)。

  3. 第三:(简单)将ListB上留下的任何条目添加到ListA中(我们需要最终在ListA上得到的列表)。

讨论

现在,是的,我可以手动遍历每个列表,但问题更多地涉及优雅和性能。Union仅应用一种“不同”的操作,使重复项保留下来。

使用VB和/或LINQ,但可以从C#转换...

更新-LINQ Intersect不喜欢自定义/用户类型(类):

List1: ip: 85.94.160.0 net: 255.255.224.0 hash: 35462368
List1: ip: 91.187.64.0 net: 255.255.224.0 hash: 15720800
List1: ip: 109.111.96.0 net: 255.255.224.0 hash: 27477092
List1: ip: 185.4.52.0 net: 255.255.252.0 hash: 19444704
List1: ip: 194.158.64.0 net: 255.255.224.0 hash: 65489923

List2: ip: 85.94.160.0 net: 255.255.224.0 hash: 45276315
List2: ip: 91.187.64.0 net: 255.255.224.0 hash: 10391797
List2: ip: 109.111.96.0 net: 255.255.224.0 hash: 29919882
List2: ip: 185.4.52.0 net: 255.255.252.0 hash: 13173532
List2: ip: 194.158.64.0 net: 255.255.224.0 hash: 65387957

(哈希是每个实例的.GetHashCode()的输出)
我能否覆盖LINQ的Intersect正在使用的比较器函数? 我在网上没有找到太多关于LINQ的Intersect函数如何运作(它用于判断“相等性”)...

针对VB.NET开发人员:

这是user2321864的解决方案,但使用VB.NET实现:

Dim a = New List(Of Integer) From {2, 4, 6, 8}
Dim b = New List(Of Integer) From {1, 2, 3, 5, 7}

'find items common in both lists
Dim dupes = a.Intersect(b).ToList()

'delete common items from both lists
a.RemoveAll(Function(x) dupes.Contains(x))
b.RemoveAll(Function(x) dupes.Contains(x))

3
你只需要重写Equals和GetHashCode方法,就可以根据属性值验证它们是否相等。你还可以为你的POCOs创建一个IEqualityComparer实现来使用。 - Maurice Reeves
3个回答

2
LINQ的Intersect方法会返回两个列表中共同存在的项。
var a = new List<int>{2,4,6,8};
var b = new List<int>{1,2,3,5,7};

//find items common in both lists
var dupes = a.Intersect(b).ToList();

//delete common items from both lists
a.RemoveAll(x => dupes.Contains(x));
b.RemoveAll(x => dupes.Contains(x));

感谢您的回复。ListA中的条目在路由器上被视为被阻止的网络,这就是为什么我不能只是将它们全部放在设备上并重新插入它们的原因... :) - Compassionate Narcissist
你可能也可以使用 a.Except(b)b.Except(a) - jessehouwing
好的,如果您使用常见类型,这个解决方案会非常好。在我的情况下,列表(尽管它们具有完全相同的项目类型)在我执行GetHashCode时具有不同的项目...我将在另一个更新中详细说明... - Compassionate Narcissist

1
这是最终版本,可以解决问题。我只是将IP和子网连接起来进行哈希处理,以便始终有一种一致的方式。只要您以相同的方式组合要用于相等性的元素,并且在使用过程中保持一致,就可以使用任何内容作为相等性哈希输入。
重点是.GetHashCode和.Equals相关联。这一点在SO的其他帖子中也有提到。对我这个程序员来说,我们可以重写这些函数以适应我们的自定义对象,这是一件很棒的事情!
它可以在VB中修改以适用于任何自定义类型...
感谢大家!
Public Class NetworkEntry
    [...]
    '
    ' override base functions for proper .Equals(x) operation
    '
    Public Overrides Function GetHashCode() As Integer
        Dim concat As String = Me.HostAddress.ToString & Me.SubnetAddress.ToString
        Return concat.GetHashCode
    End Function
    '
    Public Overloads Function Equals(obj As NetworkObject) As Boolean
        Dim equal As Boolean = False
        If (Me.HostAddress.ToString = obj.HostAddress.ToString) And
            (Me.SubnetAddress.ToString = obj.SubnetAddress.ToString) Then
                equal = True
        End If
        Return equal
    End Function
    [...]
End Class

感谢大家的贡献!

-1

在对两个列表进行排序后(需要 O[n log n] + O[m log m] 的时间复杂度),您可以通过简单地迭代两个列表来以 O(max(n,m)) 的时间复杂度解决此问题。


如果有一个关于如何实现你的建议的示例,我至少能够给你更多的反馈。 :) - Compassionate Narcissist
1
抱歉,我知道这有点抽象,但基本上有很多方法可以做到。我的目标是用时间复杂度作为主要考虑因素以一种通用的方式来解释它,因为您正在寻求性能方面的建议。Linq可能在Intersect扩展方法的后端执行相同操作(您可以通过ILSpy或类似反编译器进行检查)。 - Dennis Degryse

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接