【问题标题】:should i use Except or Contains when dealing with HashSet or so in Linq在 Linq 中处理 HashSet 左右时我应该使用 except 还是 Contains
【发布时间】:2011-08-26 23:04:10
【问题描述】:

看看这个:

 var query = myDic.Select(x => x.Key).Except(myHashSet);

 var query = myDic.Select(x => x.Key).where(y=>!myHashSet.Contains(y))

我猜由于第一种情况下的多态性,将调用 O(1) 版本的 Contains。 不过不知道except

更新

就我而言,Exept 也是 O(1)。

why linq's `except` extension method does not have Except<TSource> Method (IEnumerable<TSource>,HashSet<TSource>) overload?

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    如果您的 myDic 是普通的 .NET 字典,那么我会选择

    myDic.Keys.Except(myHashSet)
    

    为了可读性。

    说到你的选择,第一个是 O(n+m) 而第二个是 O(n),这两者都没有告诉你哪个先完成你的集合大小。如有疑问,请两匹马比赛。

    @sehe 的答案也是 O(n+m),但很可能它会比您的 O(n+m) 解决方案更快。

    【讨论】:

      【解决方案2】:

      var query = myDic.Select(x => x.Key).Except(myHashSet);

      Except 将是 IEnumerable 上的扩展(Select 的结果)。这不是 O(1)

      myHashSet.Contains(y) 确实是在调用成员函数,也就是O(n)


      考虑

      new HashSet<K>(myDic.Select(x => x.Key)).ExceptWith(myHashSet);
      

      另外看看HashSet.SymmetricExceptWith()

      【讨论】:

      • 实际上,Enumerable.Except() O(n)(或者更确切地说是 O(n + m)),它在内部使用了一个哈希集。您创建新 HashSet 的版本具有相同的时间复杂度。
      • @svick:请原谅草率的错字。那应该在那里说O(1)......;当然,在同一行中创建一个临时 HashSet 不会获得太多收益,但如果键集没有太大变化,它可以被缓存。
      • @svick: 如果Except 在内部使用哈希集,为什么不是 O(1)?只要传入的参数已经是HashSet
      • @colinfang,因为它必须至少遍历两个集合之一。
      • @svick:啊哈,我的意思是在每次查询迭代中它是 O(1),你提到了整个流。误会你了。但是,我仍然担心在Except() 中它使用构造器:new Hashset(ICollection),恐怕myHashSet 的大小仍然很重要,尽管不再乘以查询迭代。这就是为什么你说 O(n+m) 不是吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-02
      • 2017-01-29
      • 1970-01-01
      • 2023-02-07
      • 2015-10-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多