【问题标题】:How to remove duplicate (user-defined classes) entries that both Lists have in common?如何删除两个列表共有的重复(用户定义的类)条目?
【发布时间】:2014-06-16 00:27:21
【问题描述】:

奇怪的是没有更多关于这个。

短版

ListA 有一些 ListB 有的元素,有一些没有。 ListB 有一些 ListA 有的元素,有些没有。 ...事实上,绝大多数都是骗子。

注意:这些元素不是常见类型,而是来自我创建的一个类...(LINQ Intersect 似乎只适用于已知类型 - 请参阅下面的更新)

如何删除两个列表中它们共有的条目

加长版

-A 设备上有 ListA 项目,我想将它与 ListB 的项目同步。我不想删除并制作新的。这不是一个可能的选择。

-要同步列表,我会:

第一:

  1. (?) 删除它们之间的任何重复(这些条目已经同步, 毕竟)。

  2. second:(简单)删除任何剩余的 ListA 条目(因为它们不是 在 ListB 上,否则它们会被当作骗子删除)。

  3. 第三个:(简单)将 ListB 上剩余的任何条目添加到 ListA(我们的 List 需要以 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

(hash 表示每个实例的 .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))

【问题讨论】:

  • 您需要做的就是覆盖 Equals 和 GetHashCode,您可以根据属性值验证它们是否被视为相等。您还可以为您的 POCO 创建一个 IEqualityComparer 的实现,您可以使用它。

标签: vb.net linq list


【解决方案1】:

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));

【讨论】:

  • +user2321864 谢谢。 ListA 中的条目作为阻塞网络位于路由器上,这就是为什么我不能在设备上将它们全部打掉并重新插入它们...... :)
  • 你也可以使用a.Except(b)b.Except(a)
  • 好吧,如果你使用通用类型,这个解决方案最终会很棒。就我而言,列表(尽管它们具有相同的确切项目类型)在我执行 GetHashCode 时具有不同的项目...我将在上面的另一个更新中详细说明...
【解决方案2】:

这最终成为了可以解决问题的最终版本。我只是将 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

感谢大家的意见!

【讨论】:

    【解决方案3】:

    在对两个列表进行排序后(需要 O[n log n] + O[m log m]),您只需遍历两个列表即可在 O(max(n,m)) 中解决此问题。

    【讨论】:

    • 我知道,如果有一个示例说明我将如何按照您的建议进行操作,我至少可以给您更多反馈。 :)
    • 对不起,是的,这有点抽象,但基本上有很多方法可以做到这一点。我的目标是以通用方式解释它,主要关注时间复杂度,因为您正在寻找性能。 Linq 可能在 Intersect 扩展方法的后端做同样的事情(你可以通过 ILSpy 或类似的反编译器检查)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多