检查重复项时的性能

时间:2008-09-18 12:10:01

标签: c# performance collections .net-2.0

我一直致力于一个项目,我需要遍历一组数据并删除重复“主键”的条目。我尝试过使用

List<int>

Dictionary<int, bool>

使用字典我发现性能略好,即使我从不需要为每个条目标记布尔值。我的期望是这是因为List允许索引访问而Dictionary不允许。我想知道的是,这个问题是否有更好的解决方案。我不需要再次访问这些条目,我只需要跟踪我看到的“主键”,并确保我只对具有新主键的条目执行附加工作。我正在使用C#和.NET 2.0。我无法控制修复输入数据以从源中删除重复项(不幸的是!)。所以你可以有一个扩展的感觉,总的来说我在应用程序中检查重复约1,000,000次,但是在不超过64,000的子集中需要是唯一的。

6 个答案:

答案 0 :(得分:3)

他们在.NET 3.5中添加了HashSet类。但我猜它会与词典相提并论。如果你有少于100个元素,List可能会表现得更好。

答案 1 :(得分:1)

编辑:没关系我的评论。我以为你在谈论C ++。我不知道我的帖子是否与C#世界有关..

哈希表可能会更快一些。二进制树(这是字典中使用的)由于访问内存的方式而倾向于相对较慢。如果树变得非常大,则尤其如此。

但是,在更改数据结构之前,您是否尝试为字典使用自定义池分配器?我敢打赌,时间不是花在遍历树本身上,而是在数百万的分配和解除分配中,字典将为你做。

您可能会看到一个因素10速度提升只是将一个简单的池分配器插入字典模板。 Afaik boost有一个可以直接使用的组件。

另一种选择:如果您知道整数中只有64.000个条目,您可以将它们写入文件并为其创建完美的哈希函数。这样你就可以使用hash函数将你的整数映射到0到64.000范围并索引一个位数组。

可能是最快的方式,但不太灵活。每次整数集更改时,您都必须重做完美的哈希函数(可以自动完成)。

答案 2 :(得分:0)

我真的不明白你的要求。

首先恰恰与你所说的完全相反。字典具有索引访问权限(是哈希表),而de List没有。

如果你已经在字典中有数据,那么所有的键都是唯一的,就不会有重复。

我认为您将数据存储在另一种数据类型中,然后将其存储到字典中。如果是这种情况,插入数据将适用于两个字典。

foreach (int key in keys)
{
  if (!MyDataDict.ContainsKey(key))
  {
    if (!MyDuplicatesDict.ContainsKey(key))
      MyDuplicatesDict.Add(key);
  }
  else
    MyDataDict.Add(key); 
}

答案 3 :(得分:0)

如果要检查整数的唯一性,并且整数范围受到足够的限制,那么您可以使用数组。

为了更好地打包,您可以实现位图数据结构(基本上是一个数组,但是数组中的每个int通过每个键使用1位来表示密钥空间中的32个int)。这样,如果最大数量是1,000,000,那么数据结构只需要~30.5KB的内存。

位图的执行将是O(1)(每次检查),这很难被击败。

答案 4 :(得分:0)

removing duplicates from an array上有一段时间的问题。出于问题的目的,性能不是很重要,但您可能希望看一下答案,因为它们可能会给您一些想法。此外,我可能不在这里,但如果您尝试从数组中删除重复项,那么像Enumerable.Distinct这样的LINQ命令可能会比您自己编写的内容提供更好的性能。事实证明,有一种方法可以获得LINQ working on .NET 2.0所以这可能是一条值得研究的路线。

答案 5 :(得分:0)

如果您要使用List,请使用BinarySearch:

 // initailize to a size if you know your set size
List<int> FoundKeys = new List<int>( 64000 );
Dictionary<int,int> FoundDuplicates = new Dictionary<int,int>();

foreach ( int Key in MyKeys )
{
   // this is an O(log N) operation
   int index = FoundKeys.BinarySearch( Key );
   if ( index < 0 ) 
   {
       // if the Key is not in our list, 
       // index is the two's compliment of the next value that is in the list
       // i.e. the position it should occupy, and we maintain sorted-ness!
       FoundKeys.Insert( ~index, Key );
   }
   else 
   {
       if ( DuplicateKeys.ContainsKey( Key ) )
       {
           DuplicateKeys[Key]++;
       }
       else
       {
           DuplicateKeys.Add( Key, 1 );
       }
   } 
} 

您也可以将此用于可以通过使用重载来定义IComparer的任何类型:BinarySearch(T item,IComparer&lt; T&gt;);