什么是在.net 2中生成唯一集的最快方法

我有一个基本上是锯齿状的名称值对数组 – 我需要从中生成一组唯一的名称值。 锯齿状arrays约为86,000 x 11值。 对我来说,以什么方式存储名称值对(单个字符串“name = value”或专门的类,例如KeyValuePair)并不重要。
附加信息:有40个不同的名称和更多的不同值 – 可能在10,000个值的区域内。

我正在使用C#和.NET 2.0(并且性能非常差)我认为将整个锯齿状数组推送到sql数据库并从那里做一个不同的选择可能会更好。

以下是我使用的当前代码:

List<List<KeyValuePair>> vehicleList = retriever.GetVehicles(); this.statsLabel.Text = "Unique Vehicles: " + vehicleList.Count; Dictionary<KeyValuePair, int> uniqueProperties = new Dictionary<KeyValuePair, int>(); foreach (List<KeyValuePair> vehicle in vehicleList) { foreach (KeyValuePair property in vehicle) { if (!uniqueProperties.ContainsKey(property)) { uniqueProperties.Add(property, 0); } } } this.statsLabel.Text += "\rUnique Properties: " + uniqueProperties.Count; 

我让它从9分钟以来的0.34秒内运行

问题是比较KeyValuePair结构。 我通过编写比较器对象并将其实例传递给Dictionary来解决它。

根据我的判断,KeyValuePair.GetHashCode()返回它的Key对象的哈希码(在这个例子中是最不唯一的对象)。

当字典添加(并检查存在)每个项目时,它使用Equals和GetHashCode函数,但是当哈希码不太独特时必须依赖于Equals函数。

通过提供更独特的GetHashCode函数,它远远不如Equals函数。 我还优化了Equals函数,以便在较少的unqiue键之前比较更独特的值。

使用下面的比较器对象,在0.34秒内运行86,000 * 11个具有10,000个唯一属性的项目(没有比较器对象需要9分22秒)

希望这可以帮助 :)

  class StringPairComparer : IEqualityComparer> { public bool Equals(KeyValuePair x, KeyValuePair y) { return x.Value == y.Value && x.Key == y.Key; } public int GetHashCode(KeyValuePair obj) { return (obj.Key + obj.Value).GetHashCode(); } } 

编辑 :如果它只是一个字符串(而不是KeyValuePair,其中string = Name + Value),它将大约快两倍。 这是一个很好的有趣的问题,我花费了很多时间 (虽然我学会了安静)

如果您不需要每个键/值对与您生成的唯一值之间的任何特定关联,您可以只使用GUID? 我假设问题是你当前的’Key’在这个锯齿状数组中不是唯一的。

 Dictionary> myDict = new Dictionary>(); foreach of your key values in their current format myDict.Add(System.Guid.NewGuid(), new KeyValuePair(yourKey, yourvalue)) 

听起来它会存储你需要的东西,但我不知道你将如何从中提取数据,因为生成Guid和你原来拥有的东西之间没有语义关系……

你能在问题中提供更多信息吗?

使用KeyValuePair作为包装类,然后创建一个字典,以创建一个集合? 或者实现自己的包装器来覆盖Equals和GetHashCode。

 Dictionary mySet; for(int i = 0; i < keys.length; ++i) { KeyValuePair kvp = new KeyValuePair(keys[i], values[i]); mySet[kvp] = true; } 

而不是使用Dictionary为什么不扩展KeyedCollection ? 根据文件:

为其键嵌入值的集合提供抽象基类。

然后,您需要覆盖protected TKey GetKeyForItem(TItem item)函数。 因为它是IListIDictionary之间的混合体IDictionary我认为它可能非常快。

怎么样:

 Dictionary hs = new Dictionary(); foreach (i in jaggedArray) { foreach (j in i) { if (!hs.ContainsKey(j)) { hs.Add(j, 0); } } } IEnumerable unique = hs.Keys; 

当然,如果您使用的是C#3.0,.NET 3.5:

 var hs = new HashSet(); hs.UnionWith(jaggedArray.SelectMany(item => item)); 

会做的伎俩。

你有没有描述过你的代码? 您确定foreach循环是瓶颈,而不是Retriever.GetVehicles()?

我确实创建了一个小测试项目,我伪造了检索器并让它返回86.000 X 11值。 我的第一次尝试在5秒时运行,创建了包含的数据。

我对键和值使用了相同的值,其中第一个键是“0#0”,最后一个是“85999#10”。

然后我切换到guids。 结果相同。

然后我把钥匙做得更长了,像这样:

  var s = Guid.NewGuid().ToString(); return s + s + s + s + s + s + s+ s + s + s; 

现在花了差不多10秒钟。

然后我疯狂地把钥匙弄得很长,并且出现了内存exception。 我的计算机上没有交换文件,所以我立即得到了这个例外。

你的钥匙多长时间了? 你的虚拟内存消耗是你性能不佳的原因吗?