使用 HashSet 作为字典键 - 比较所有元素

Use HashSet as Dictionary Key - Compare all elements

我正在检查一组边是否已经包含 2 个点之间的连接。

我想使用包含 2 个向量的 HashSet 作为 Dictionary 键。然后我希望能够调用一个性能Dictionary.ContainsKey(hashSet)。我希望 contains/equality 检查依赖于集合中的向量。

费。如果我将 HashSet [V000 V001] 添加到字典中。我想让 Dictionary.ContainsKey(HashSet [V001 V000]) return 为真。 (HashSet,所以顺序可以不同,只是元素相同)

问题似乎是,Dictionary.ContainsKey() 方法确实将单独创建的 HashSets 视为不同的对象,尽管它们包含相同的元素。

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

您还可以建议一种更好的方法来执行此操作'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());
    }
}      

您想使用哈希集作为键。

所以键是引用,其中一个键是一个哈希集引用。

ContainsKey 比较引用。

对于您想做的事情,您可以创建一个 class 实现 IEqualityComparer 以将其传递给字典构造函数。

https://docs.microsoft.com/dotnet/api/system.collections.generic.iequalitycomparer-1

如果你想要一个完整的管理,你应该创建一个新的 class 嵌入字典并实现你自己的 public 包装字典的操作: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();

  ...

}

因此您将拥有一个适合您预期用途的强类型字典。