C# 使用HashSet作为字典键-比较所有元素
我正在检查整个边组是否已包含两点之间的连接 我想使用包含两个向量的C# 使用HashSet作为字典键-比较所有元素,c#,dictionary,hashset,edges,C#,Dictionary,Hashset,Edges,我正在检查整个边组是否已包含两点之间的连接 我想使用包含两个向量的哈希集,作为字典键。然后我希望能够调用performantDictionary.ContainsKey(hashSet)。我希望包含/相等检查依赖于集合中的向量 氧化铁。如果我将HashSet[v000v001]添加到Dict中,我希望得到Dictionary.ContainsKey(HashSet[V001 V000])返回true。(HashSet,因此顺序可以不同,只是相同的元素) 问题似乎是,Dictionary.Cont
哈希集
,作为字典
键。然后我希望能够调用performantDictionary.ContainsKey(hashSet)
。我希望包含/相等检查依赖于集合中的向量
氧化铁。如果我将HashSet[v000v001]
添加到Dict中,我希望得到Dictionary.ContainsKey(HashSet[V001 V000])
返回true。(HashSet,因此顺序可以不同,只是相同的元素)
问题似乎是,Dictionary.ContainsKey()
方法确实将单独创建的hashset
视为不同的对象,即使它们包含相同的元素
Dictionary<HashSet<Vector3>, Vector3> d = new Dictionary<HashSet<Vector3>, Vector3>();
HashSet<Vector3> s = new HashSet<Vector3>();
s.Add(Vector3.one);
s.Add(Vector3.zero);
d.Add(s);
HashSet<Vector3> s2 = new HashSet<Vector3>();
s2.Add(Vector3.zero);
s2.Add(Vector3.one);
bool doesContain = d.ContainsKey(s2); // should be true
Dictionary d=newdictionary();
HashSet s=新的HashSet();
s、 添加(矢量3.1);
s、 加法(矢量3.0);
d、 添加(s);
HashSet s2=新的HashSet();
s2.相加(矢量3.零);
s2.添加(矢量3.1);
bool doesContain=d.ContainsKey(s2);//应该是真的
您还可以建议一种更好的方法来有效地执行“Contains()”检查。HashSet类型无法进行您想要的即时相等比较。它只有引用等式 要获得所需的内容,需要使用新类型作为字典键。新类型将具有HashSet属性,并重载
Equals()
和GetHashCode()
,此时还可以实现IEquatable
我会让你开始:
public class HashKey<T> : IEquatable<HashKey<T>>
{
private HashSet<T> _items;
public HashSet<T> Items
{
get {return _items;}
private set {_items = value;}
}
public HashKey()
{
_items = new HashSet<T>();
}
public HashKey(HashSet<T> initialSet)
{
_items = initialSet ?? new HashSet();
}
public override int GetHashCode()
{
// I'm leaving this for you to do
}
public override bool Equals(Object obj)
{
if (! (obj is HashKey)) return false;
return this.GetHashCode().Equals(obj.GetHashCode());
}
public bool Equals(HashSet<T> obj)
{
if (obj is null) return false;
return this.GetHashCode().Equals(obj.GetHashCode());
}
}
公共类HashKey:IEquatable
{
私有HashSet_项;
公共哈希集项
{
获取{return\u items;}
私有集{u items=value;}
}
公钥
{
_items=newhashset();
}
公共HashKey(HashSet initialSet)
{
_items=initialSet??新HashSet();
}
公共覆盖int GetHashCode()
{
//我把这件事留给你做
}
公共覆盖布尔等于(对象对象对象)
{
如果(!(obj是HashKey))返回false;
返回此.GetHashCode().Equals(obj.GetHashCode());
}
公共布尔等于(HashSet obj)
{
如果(obj为空)返回false;
返回此.GetHashCode().Equals(obj.GetHashCode());
}
}
您想使用哈希集作为键
所以键是引用,其中一个键是一个hashset引用
容器可以比较引用
对于要执行的操作,可以创建一个实现IEqualityComparer的类,将其传递给字典构造函数
如果你想要一个完整的管理,你应该创建一个嵌入字典的新类,并实现你自己的公共操作来包装字典:ContainsKey和所有你需要的其他方法
public class MyDictionary : IEnumerable<>
{
private Dictionary<HashSet<Vector3>, Vector3> d
= new Dictionary<HashSet<Vector3>, Vector3>();
public int Count { get; }
public this...
public ContainsKey()
{
// implements your own comparison algorithm
}
public Add();
public Remove();
...
}
公共类MyDictionary:IEnumerable
{
私人词典d
=新字典();
公共整数计数{get;}
公开这个。。。
公共容器
{
//实现您自己的比较算法
}
公共添加();
公众移除();
...
}
因此,您将有一个强类型字典用于您的预期用途。您需要一个新类型用作字典键。新类型将有一个Hashset属性,并重载
.Equals()
和GetHashCode()
(因此也可以实现IEquatable
)来进行所需的比较。HashSet
类型不提供您想要的开箱即用的相等比较。它只是引用平等。不要因为我是新来的就否决我的问题。。。非常不礼貌@JoelCoehoorn这似乎是一个非常好的方法,但我不完全理解我需要在哪里覆盖这些东西。你能给出一个小的代码示例吗?Dictionary有一个接受自定义IEqualityComparer的构造函数:@Mechandrius这个问题被否决了,因为你没有表现出任何努力或研究来解决这个问题。如果你是新来的,我真的建议你阅读所有的帮助部分,同时也要阅读Jon Skeet的。确保你的问题尽可能好将有助于你获得更有利的结果。@DavidBrowne-Microsoft噢,我以前没有注意到这个问题。这可能是有用的。我要指出的一点是,一般来说,使用GetHashCode
作为相等比较不是一个好主意(尽管我也很内疚于使用它),因为事实上,相等的对象必须返回相等的哈希码,这并不意味着具有相等哈希码的对象是相等的。Eric Lippert处理GetHashCode
,并顺便提到了这一事实(鸽子洞原则)。@pstrjds普遍同意。。但在这种情况下,这实际上是这种类型存在的唯一原因。当然,以后总是会有范围/功能的蔓延。我可以看到并同意这一点:)就因为OP是一名学生,我想确保有人提到,一般来说,这不是“最佳实践”。这看起来就是答案。但是虽然我对这个问题不太了解,但感觉有点不对劲。谢谢你的回答。两种解决方案都很好。但是使用包装的HashSet键看起来非常简单和合适。当需要更多特殊属性时,重写整个字典可能会很有用。