Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/283.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.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# HashSet的快速交集<;int>;和列表<;int>;_C#_Algorithm_Performance_Intersection_Hashset - Fatal编程技术网

C# HashSet的快速交集<;int>;和列表<;int>;

C# HashSet的快速交集<;int>;和列表<;int>;,c#,algorithm,performance,intersection,hashset,C#,Algorithm,Performance,Intersection,Hashset,我有一个HashSet和一个List(HashSet大约有300万项,List大约有30万项) 我目前使用 var intersected = hashset.Intersect(list).ToArray(); 我想知道是否有更快的方法来做到这一点。可能是并行的?是的,您可以走得更快,因为您已经有了一个哈希集。LINQ使用,这实际上是每次调用时从头开始重新创建哈希集。下面是一个更快的算法: /// <summary>Yields all the elements of first

我有一个
HashSet
和一个
List
(HashSet大约有300万项,List大约有30万项)

我目前使用

var intersected = hashset.Intersect(list).ToArray();

我想知道是否有更快的方法来做到这一点。可能是并行的?

是的,您可以走得更快,因为您已经有了一个
哈希集。LINQ使用,这实际上是每次调用时从头开始重新创建
哈希集。下面是一个更快的算法:

/// <summary>Yields all the elements of first (including duplicates) that also
/// appear in second, in the order in which they appear in first.</summary>
public static IEnumerable<TSource> Intersect<TSource>(IEnumerable<TSource> first,
    HashSet<TSource> second)
{
    foreach (TSource element in first)
    {
        if (second.Contains(element)) yield return element;
    }
}
我不希望它更快,如果有的话,因为工作量很大。调用lambda 300000次的开销可能会掩盖并行性的任何好处


此外,除非在查询中添加PLINQ方法,否则不会保留结果的顺序,从而进一步影响操作的性能。

将大量整数存储为紧凑的位集可能比存储为
哈希集
列表
(至少如果您使用
List
存储唯一整数,就像
HashSet
一样)。从这个意义上讲,有几种选择:

  • 内置以紧凑的方式存储每个位。例如,如果要存储从1到65000的整数,
    BitArray
    需要大约8125字节的内存(而如果每个位存储为8位字节,则需要65000字节)。但是,如果最高设置位非常大,
    BitArray
    可能不会非常高效地存储内存(例如,30亿),或者如果该组位是稀疏的(存在具有设置位和/或清除位的巨大区域)。可以使用该方法将两个
    位数组
    相交
  • 压缩位集同样以紧凑的方式存储每个位,但也压缩其自身的一部分以进一步节省内存,同时仍保持集操作(如交集效率)。示例包括Elias Fano编码、咆哮位图和EWAH。请参阅比较压缩位集与未压缩位集的不同实现(
    FixedBitSet
    )在性能和内存方面(注意,它们比较Java实现,但在.NET情况下可能仍然有用)

HashSet
有一种方法,即使用方法
IntersectWith
我们可以使用下一种方法将
HashSet
列表进行相交:

private static IEnumerable<int> Intersect(HashSet<int> hash, List<int> list)
{
    HashSet<int> intersect = new HashSet<int>(list);
    intersect.IntersectWith(hash);
    return intersect;
}
从表中我们可以看到,最快的方法是
HashSet Contains Parallel
,最慢的方法是
Linq Intersect



这是用来衡量性能的数据。

它们是否需要哈希集和列表?
private static IEnumerable<int> Intersect(HashSet<int> hash, List<int> list)
{
    HashSet<int> intersect = new HashSet<int>(list);
    intersect.IntersectWith(hash);
    return intersect;
}
------------------------------------------------------------------------
|         Method            | Min, ms | Max, ms | Avg, ms | StdDev, ms |
------------------------------------------------------------------------
| Linq Intersect            |   135   |   274   |   150   |     17     |
| HashSet Contains          |    25   |    44   |    26   |      2     |
| HashSet Contains Parallel |    12   |    53   |    13   |      3     |
| HashSet IntersectWith     |    57   |    89   |    61   |      4     |
------------------------------------------------------------------------