Страницы

Поиск по вопросам

суббота, 30 ноября 2019 г.

Составной ключ в Dictionary

#c_sharp #net


Допустим, есть класс, у которого есть 2 цифровых поля.

Хотелось бы эти 2 поля сделать первичным ключем в Dictionary.

В будущем этот ключ будет использоваться для поиска совпавших значений между 2 мя
словарями.

Как это можно сделать, что бы не потерять в производительности?

У меня была идея, хранить их как строку, но может быть есть решение лучше?

P.S 

Dictionary использую из-за высокой скорости поиска по ключу.

К моему удивлению, DataTable оказался тормознутее=( на 20к строк
    


Ответы

Ответ 1



Как один из вариантов Можно использовать класс Tuple. Например Dictionary, T3>, где T1, T2, T3 значения любых типов. В Tuple сравниваться будет по внутренним значениям. у Tuple переопределены методы GetHashCode и Equals © Grundy Использовать структуру, т.к. у структур идет сравнение по всем имеющимся полям Передавать IEqualityComparer в конструктор, где Т - тип ключа. Сравнение будет производиться с использованием компаратора.

Ответ 2



Есть несколько путей использовать составной ключ для Dictionary (аналогично для HashSet) Использовать структуру. Правила сравнения структур таковы, что сравниваются значения всех полей, а не ссылки на объекты. Использовать класс с переопределенными методами Equals, GetHashCode. Это позволит использовать для вычисления хэша не все поля класса, а только нужные. Использовать класс реализующий IEquatable Использовать при создании словаря перегрузку конструктора принимающую IEqualityComparer

Ответ 3



Привношу пример кода из дублирующего вопроса. Классу Dictionary для того, чтобы обращаться к элементу по ключу, надо сравнивать ключи друг с другом. Поэтому необходимо реализовать операцию сравнения двух объектов составного ключа, например, реализовав интерфейс IEquatable и переопределив метод object.Equals и object.GetHashCode. Пример реализации IEquatable и переопределения Equals и GetHashCode: public class ComplexKey : IEquatable { private int value1; private string value2; public ComplexKey(int value1, string value2) { this.value1 = value1; this.value2 = value2; } public bool Equals(ComplexKey other) { return EqualityComparer.Default.Equals(value1, other.value1) && EqualityComparer.Default.Equals(value2, other.value2); } public override bool Equals(object other) { if (other is ComplexKey) return Equals((ComplexKey)other); return false; } public override int GetHashCode() { var result = 17; unckecked { result = 31 * result + EqualityComparer.Default.GetHashCode(value1); result = 31 * result + EqualityComparer.Default.GetHashCode(value2); } return result; } } Методы Equal просто сравнивают попарно все значения составного ключа и возвращают true только тогда, когда все поля класса совпадают. Метод GetHashCode считает значение хеша способом, который на SO набрал больше всего плюсов.

Ответ 4



Вероятно, Tuple подойдёт для использования в качестве ключа.

Комментариев нет:

Отправить комментарий