Как использовать HashSet <T>в качестве словарного ключа? - PullRequest
24 голосов
/ 06 мая 2011

Я хочу использовать HashSet<T> в качестве ключа к словарю:

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

Я хочу найти значения из словаря, чтобы два разных экземпляра HashSet<T>, которые содержали одинаковые элементы , возвращали одно и то же значение.

HashSet<T> реализации Equals() и GetHashCode(), похоже, не делают этого (я думаю, что они просто по умолчанию). Я могу переопределить Equals(), чтобы использовать SetEquals(), но как насчет GetHashCode()? Я чувствую, что что-то здесь упускаю ...

Ответы [ 3 ]

37 голосов
/ 06 мая 2011

Вы можете использовать набор сравнения, предоставляемый HashSet<T>:

var myDictionary = new Dictionary<HashSet<T>, TValue>(HashSet<T>.CreateSetComparer());
7 голосов
/ 06 мая 2011

Ответ digEmAll, безусловно, является лучшим выбором на практике, так как он использует встроенный код, а не изобретает колесо. Но я оставлю это как пример реализации.


Вы можете использовать IEqualityComparer<HashSet<T>>, который использует SetEquals. Затем передайте его конструктору словаря. Что-то вроде следующего (не проверял):

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, поскольку это даст неверные результаты, если в набор был добавлен пользовательский компаратор равенства.

2 голосов
/ 06 мая 2011

Вы можете предоставить IEqualityComparer<HashSet<T>> для конструктора Dictionary и сделать желаемую реализацию в этом компараторе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...