更新: 从.Net 4.7.2开始,HashSet.TryGetValue - docs可用 HashSet.TryGetValue - SO post
我对HashSet
有疑问,因为它没有提供与TryGetValue
中已知的Dictionary
类似的任何方法。我需要这样的方法 - 传递元素在集合中查找,并从其集合中设置返回元素(找到时)。
旁注 - "为什么你需要集合中的元素,你已经有那个元素?"。不,我不是,平等和身份是两回事。
HashSet
没有被封存,但是它的所有字段都是私有的,因此从中得出它是毫无意义的。我无法使用Dictionary
,因为我需要SetEquals
方法。我正在考虑抓取HashSet
的源并添加所需的方法,但许可证不是真正的开源(我可以看,但我无法分发/修改)。我可以使用反射,但HashSet
中的数组不是readonly
,这意味着我无法在每个实例生命周期内绑定到这些字段。
我不想仅仅为单堂课使用完整的图书馆。
到目前为止,我遇到了LINQ SingleOrDefault
。所以问题是如何解决这个问题 - HashSet
与TryGetValue
?
答案 0 :(得分:4)
您可能应该从www.site.com/DC/citydata
切换到HashSet
SortedSet
有一个简单的TryGetValue()
:
SortedSet
调用时,元素只需要在Comparer中使用的所有属性集。它返回在Set中找到的元素。
答案 1 :(得分:3)
我同意这是基本上缺失的东西。虽然它仅在极少数情况下有用,但我认为它们是罕见的重要案例 - 最值得注意的是,关键的规范化。
我现在只能想到一个建议,这真的是犯规。
您可以在创建IEqualityComparer<T>
时指定自己的HashSet<T>
- 因此请创建一个记住其执行的最后一次正(即真正返回)Equals
比较的参数。然后,您可以调用Contains
,并查看要求相等比较器进行比较的内容。
注意事项:
HashSet<T>
没有使用任何优化,例如&#34;如果引用相同,请不要咨询相等比较器&#34; 我一直试图在寻找十字路口方面考虑其他选择,但我还没有到达任何地方......
正如评论中所指出的那样,尽可能将其封装起来是值得的 - 我怀疑你只需要一组非常有限的操作,所以我要在你自己的班级中包装HashSet<T>
暴露你真正需要的操作 - 这样你就可以清除&#34;缓存&#34;每次操作后,删除我上面的第一个异议。
对我来说,这仍然是一种可怕的虐待,但是......
正如其他人所建议的那样,另一种方法是使用Dictionary<TKey, TValue>
并自己实施SetEquals
。这很简单 - 再次,你想要将它封装在你自己的类型中。无论哪种方式,您都应该首先设计类型本身,然后使用HashSet<>
或Dictionary<,>
作为实现细节来实现它。
答案 2 :(得分:2)
听起来像是在尝试使用错误的工具。没错,您可以使用HashSet保存一些内存,但在我看来,您正试图实现不同的目标:获取与表示相等的实际元素。 所以实际上它们是两个不同的元素。只有memento(唯一的表示)是相等的。
因此,您最好使用字典,将元素添加为键 和 值。所以你可以把它拿回来(相同),但你错过了SetEquals
....
我认为SetEquals
在其实现中没有什么不同于顺序比较它的桶顺序中的两个HashSets并且在第一个不相等时失败。
所以你应该同样使用简单的SequenceEqual()
(LINQ)比较两个Keys
集合。
所以这个扩展方法可以做到
public static SetEqual<T,G>(this IDictionary<T,G> d, IDictionary<T,G> e)
{
return d.Keys.SequenceEqual(e.Keys);
}
这应该有效,因为Dictionary
基本上是具有关联值的HashSet。而且更适合你的问题。 (好的,为了正确,代码应该是Dictionary<>
而不是IDictionary<>
,因为关键顺序很重要)
如果你需要第二个参数IEnumerable<>
,请尝试排序以获得定义的顺序(效率不高)。
答案 3 :(得分:1)
答案 4 :(得分:0)
希望不要盲目但我没有在任何地方看到这个答案。如果你想要字典TryGetValue
,你可以偷它。
theHashset.ToDictionary(item => item.ID).TryGetValue(key, out value)
您需要的只是一个用于确定唯一键的快速lambda。