如何使用 HashSet作为字典键?

发布于 2024-11-05 14:31:11 字数 491 浏览 0 评论 0 原文

我希望使用 HashSet 作为字典的键:

Dictionary<HashSet<T>, TValue> myDictionary = new Dictionary<HashSet<T>, TValue>();

我想从字典中查找值,这样 HashSet 的两个不同实例 < em>包含相同的项目将返回相同的值。

HashSetEquals()GetHashCode() 实现似乎没有这样做(我认为它们只是默认值)。我可以重写 Equals() 以使用 SetEquals(),但是 GetHashCode() 又如何呢?我感觉我在这里失去了一些东西......

I wish to use HashSet<T> as the key to a Dictionary:

Dictionary<HashSet<T>, TValue> myDictionary = new Dictionary<HashSet<T>, TValue>();

I want to look up values from the dictionary such that two different instances of HashSet<T> that contain the same items will return the same value.

HashSet<T>'s implementations of Equals() and GetHashCode() don't seem to do this (I think they're just the defaults). I can override Equals() to use SetEquals() but what about GetHashCode()? I feel like I am missing something here...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

奈何桥上唱咆哮 2024-11-12 14:31:11

您可以使用 HashSet 提供的集合比较器:

var myDictionary = new Dictionary<HashSet<T>, TValue>(HashSet<T>.CreateSetComparer());

You could use the set comparer provided by HashSet<T>:

var myDictionary = new Dictionary<HashSet<T>, TValue>(HashSet<T>.CreateSetComparer());
A君 2024-11-12 14:31:11

digEmAll 的答案显然是实践中更好的选择,因为它使用内置代码而不是重新发明轮子。但我将把它作为示例实现。


您可以使用 SetEquals 实现一个 IEqualityComparer>。然后将其传递给字典的构造函数。类似以下内容(未测试):

class HashSetEqualityComparer<T>: IEqualityComparer<HashSet<T>>
{
    public int GetHashCode(HashSet<T> hashSet)
    {
        if(hashSet == null)
           return 0;
        int h = 0x14345843; //some arbitrary number
        foreach(T elem in hashSet)
        {
            h = unchecked(h + hashSet.Comparer.GetHashCode(elem));
        }
        return h;
    }

    public bool Equals(HashSet<T> set1, HashSet<T> set2)
    {
        if(set1 == set2)
            return true;
        if(set1 == null || set2 == null)
            return false;
        return set1.SetEquals(set2);
    }
}

请注意,这里的哈希函数是可交换的,这很重要,因为集合中元素的枚举顺序是未定义的。

另一个有趣的点是,您不能只使用 elem.GetHashCode ,因为当向集合提供自定义相等比较器时,这会给出错误的结果。

digEmAll's answer is clearly the better choice in practice, since it uses built in code instead of reinventing the wheel. But I'll leave this as a sample implementation.


You can use implement an IEqualityComparer<HashSet<T>> that uses SetEquals. Then pass it to the constructor of the Dictionary. Something like the following(Didn't test it):

class HashSetEqualityComparer<T>: IEqualityComparer<HashSet<T>>
{
    public int GetHashCode(HashSet<T> hashSet)
    {
        if(hashSet == null)
           return 0;
        int h = 0x14345843; //some arbitrary number
        foreach(T elem in hashSet)
        {
            h = unchecked(h + hashSet.Comparer.GetHashCode(elem));
        }
        return h;
    }

    public bool Equals(HashSet<T> set1, HashSet<T> set2)
    {
        if(set1 == set2)
            return true;
        if(set1 == null || set2 == null)
            return false;
        return set1.SetEquals(set2);
    }
}

Note that the hash function here is commutative, that's important because the enumeration order of the elements in the set is undefined.

One other interesting point is that you can't just use elem.GetHashCode since that will give wrong results when a custom equality comparer was supplied to the set.

断桥再见 2024-11-12 14:31:11

您可以向 Dictionary 构造函数提供 IEqualityComparer> 并在该比较器中进行所需的实现。

You can provide a IEqualityComparer<HashSet<T>> to the Dictionary constructor and make the desired implementation in that comparer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文