Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在创建3个IEnumerables的并集时,实现O(n)性能的最简单方法是什么?_C#_Linq - Fatal编程技术网

C# 在创建3个IEnumerables的并集时,实现O(n)性能的最简单方法是什么?

C# 在创建3个IEnumerables的并集时,实现O(n)性能的最简单方法是什么?,c#,linq,C#,Linq,假设a、b、c都是List,我想创建它们的未排序并集。虽然性能不是非常关键,但它们可能每个都有10000个条目,所以我希望避免使用O(n^2)解决方案 AFAICT MSDN文档没有说明任何关于union的性能特征,因为不同的类型是相关的 我的直觉告诉我,如果我只做a.Union(b).Union(c),这将需要O(n^2)时间,但是新的Hashset(a).Union(b).Union(c)将是O(n) 是否有人有任何文档或指标来确认或否认此假设?您应该使用Enumerable.Union,因

假设a、b、c都是
List
,我想创建它们的未排序并集。虽然性能不是非常关键,但它们可能每个都有10000个条目,所以我希望避免使用O(n^2)解决方案

AFAICT MSDN文档没有说明任何关于union的性能特征,因为不同的类型是相关的

我的直觉告诉我,如果我只做
a.Union(b).Union(c)
,这将需要O(n^2)时间,但是
新的Hashset(a).Union(b).Union(c)
将是O(n)


是否有人有任何文档或指标来确认或否认此假设?

您应该使用
Enumerable.Union
,因为它与
哈希集
方法一样有效。复杂性为O(n+m),因为:

枚举此方法返回的对象时,
Union
e按顺序计算第一个和第二个并生成 还没有屈服

源代码



是的,如果对多个集合使用
Enumerable.Union
,则会产生开销,因为必须为每个链接调用创建一个新集合。因此,如果您使用以下方法之一,可能会更有效(在内存消耗方面):

  • Concat
    +
    Distinct

    a.Concat(b).Concat(c)...Concat(x).Distinct()
    
  • Union
    +
    Concat

    a.Union(b.Concat(c)...Concat(x))
    
  • 这需要
    IEnumerable
    (f.e.with
    int
    ):

    新哈希集(a.Concat(b.Concat(c)…Concat(x))
    

  • 前两者之间的差异可能可以忽略不计。第三种方法不是使用延迟执行,而是在内存中创建一个
    HashSet
    。这是一个好的、有效的方法。如果您需要此集合类型或2。如果这是查询的最终操作。但是,如果您需要对这个链式查询进行进一步的操作,您应该选择
    Concat+Distinct
    Union+Concat

    ,而@Tim Schmelter对于
    可枚举.Union
    方法的线性时间复杂度是正确的,链接多个
    Union
    运算符具有隐藏的开销,即每个
    Union
    运算符在内部创建一个哈希集,该哈希集基本上与前一个运算符(加上其他项)的哈希集重复,因此与单个
    哈希集
    方法相比,使用了更多的内存

    如果我们考虑到,
    Union
    只是
    Concat
    +
    Distinct
    的一个快捷方式,那么与
    HashSet
    具有相同时间/空间复杂性的可伸缩LINQ解决方案将是:

    a.Concat(b).Concat(c)...Concat(x).Distinct()
    
    Union
    为O(n)

    a.Union(b).Union(c)
    在大多数实现中的效率低于
    a.Union(b.Concat(c))
    ,因为它会为第一个Union操作创建一个哈希集,然后为第二个Union操作创建另一个哈希集,正如其他答案所说的那样。这两种方法最终都会产生一系列使用中的
    IEnumerator
    对象,这会随着更多源的添加而增加成本


    a.Union(b).Union(c)
    在.NET Core中效率更高,因为第二个
    .Union()
    操作将生成一个包含
    a
    b
    c
    知识的单个对象,并将为整个操作创建一个散列集,同时避免了IEnumerator对象链。

    a.Union(b)。Union(c)
    在内部使用哈希集(并使用更多内存)。a)除非您经常使用它,否则30000项不是那么多。b) 这里还有其他因素,比如
    等于
    t
    的实现。c) 另一个因素:与Java不同,c#
    HashSet
    似乎没有预先调整其内部数组大小的方法,这可能会导致
    HashSet
    Enumerable出现更多问题
    更快的是a.Union(b.Concat(c))-试试看;o) 在查看实现时,它通过
    set set set=new set(比较器)创建新集合
    但我不确定是否使用c#中的
    Set
    具体类型。我没有看到在Union方法中使用Hashset。因此,我对此感到困惑。@AkashKC:
    Set
    是一个内部类,您可以找到源代码。为什么不使用
    HashSet
    ?我不知道。Afaik两者都是同时实现的,因此可能
    HashSet
    还没有准备好使用,它们希望避免将来的冲突。然而,两者都使用相似的算法。编辑我刚刚发现这个问题:谢谢你的回答。现在,我的困惑已经消除了。在github中没有类型定义的导航功能让生活有时很艰难:(不管怎样,你的评论现在已经很清楚了。谢谢!!!
    a.Concat(b).Concat(c)...Concat(x).Distinct()