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