【问题标题】:Linq - Excluding items from different list typesLinq - 从不同的列表类型中排除项目
【发布时间】:2009-05-18 22:17:34
【问题描述】:

有没有办法选择一个列表中不包含在另一个列表中的项目?例如:

list1 = From t In list1 Where Not list2.Contains(t.column1)

这给了我错误:

Value of type 'Integer' cannot be converted to '<anonymous type>'

这是有道理的,因为 list2.Contains 期望与 list2 相同的类型。但是,列表类型不同。我只想根据列比较进行选择。

【问题讨论】:

    标签: vb.net linq


    【解决方案1】:

    list2 实际上包含什么?如果你能准确地表达你的查询,我们大概可以用 LINQ 表达它。在不知道list1list2column1 的情况下很难提供帮助。

    说的是,List&lt;T&gt;.Contains 对于您检查的每个项目都将是 O(n)。如果list2 可能不小,您可能想创建一个HashSet&lt;T&gt; - 那么每个Contains 调用会快很多。

    但是话又说回来,当我们对情况有了更多了解时,我们很可能会提出一个完全不同的解决方案。请让问题尽可能具体,以获得最佳答案。

    编辑:如果 tvanfosson 的解决方案适合您并且如果您使用的是 LINQ to Objects,那么您就有一个潜在的性能坑。最好 (IMO) 在list2 上进行投影一次 并构建一个集合:

    Dim invalid = New HashSet(Of Integer)(list2.Select(Function(x) x.Id))
    list1 = From t in list1 Where Not invalid.Contains(t.column1)
    

    【讨论】:

    • 像往常一样,Jon Skeet 赢得了 linq ;)
    【解决方案2】:

    看.Except()扩展方法,结合投影:

    list1 = list1.Except(list2.Select(Function(l) l.ID))
    

    【讨论】:

    • Except 仍然需要一个相同类型的列表进行比较。
    • 然后使用投影来映射它:list1.Except(list2.Select(...))
    • 有没有办法用多列做到这一点?
    • 我不确定这个答案如何满足原始要求,即 t.column1 指定要排除的 list1 元素的一部分。
    【解决方案3】:

    你尝试过这样的事情吗?

    list1 = From t In list1 Where Not list2.Any(l => t.column1 = l.column1 AndAlso t.column2 = l.column2)
    

    我不确定它的效率如何,但我认为它应该适合你。

    【讨论】:

    • 我喜欢它的优雅,我认为它几乎就在那里。但是我遇到了这个异常:“无法转换类型为 'WhereListIterator1[ToolObject]' to type 'System.Collections.Generic.List1[ToolObject]' 的对象。”
    • 把 .ToList() 扔到最后? (整个语句用括号括起来)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-15
    • 1970-01-01
    • 2016-05-09
    • 1970-01-01
    相关资源
    最近更新 更多