Я ищу общий, двунаправленный класс словаря 1 к 1 в C # (2), т.е. a, BiDictionaryOneToOne<T, S>
который гарантированно содержит только одно из каждого значения и ключа (в любом случае до RefEquals), и поиск в котором можно искать, используя ключ или значение. Кто-нибудь знает об этом, или я должен просто реализовать его сам? Не могу поверить, что я первый, кому это нужно ...
В ответах на этот вопрос есть BiDictionary , но он не для уникальных элементов (а также не реализует RemoveByFirst (T t) или RemoveBySecond (S s)).
Спасибо!
c#
.net
collections
Джоэл ин Гё
источник
источник
Ответы:
Хорошо, вот моя попытка (основанная на Джоне - спасибо), заархивированная здесь и открытая для улучшения:
источник
Более полная реализация двунаправленного словаря:
Dictionary<TKey,TValue>
(кроме инфраструктурных):IDictionary<TKey, TValue>
IReadOnlyDictionary<TKey, TValue>
IDictionary
ICollection<KeyValuePair<TKey, TValue>>
(этот и ниже являются базовыми интерфейсами вышеупомянутых)ICollection
IReadOnlyCollection<KeyValuePair<TKey, TValue>>
IEnumerable<KeyValuePair<TKey, TValue>>
IEnumerable
SerializableAttribute
.DebuggerDisplayAttribute
(с информацией о количестве) иDebuggerTypeProxyAttribute
(для отображения пар ключ-значение в часах).IDictionary<TValue, TKey> Reverse
свойство, а также реализует все упомянутые выше интерфейсы. Все операции с одним из словарей изменяют оба.Использование:
Код доступен в моей частной платформе на GitHub: BiDictionary (TFirst, TSecond) .cs ( постоянная ссылка , поиск ).
Копия:
источник
item.Reverse
строках. Какие-либо конкретные требования к версии?KeyValuePairExts
класс в нижней части фрагмента кода.Вопрос, на который вы ссылаетесь, также показывает в этом ответе индивидуальную реализацию . Добавление RemoveByFirst и RemoveBySecond было бы тривиальным - как и реализация дополнительных интерфейсов и т. Д.
источник
Это то же самое, что и принятый ответ, но я также предоставил
Update
методы и, в общем, немного уточнил:Подобно моему ответу здесь
Несколько замечаний:
Я реализовал только
IEnumerable<>
. Я не думаю,ICollection<>
что здесь имеет смысл, поскольку все имена методов могут отличаться для этой специальной структуры коллекции. Что должно быть внутри - решать вамIEnumerable<>
. Итак, теперь у вас тоже есть синтаксис инициализатора коллекции, напримерЯ попытался создать некоторые странные исключения здесь и там - просто для целостности данных. Просто чтобы быть в безопасности, чтобы вы знали, есть ли в моем коде ошибки.
Производительность: Вы можете поиск для
Value
либо изKeys
, что средстваGet
иContains
метод требуют только один поиска (O (1)).Add
требуется 2 просмотра и 2 добавления.Update
требуется 1 поиск и 2 добавления.Remove
занимает 3 просмотра. Все похоже на принятый ответ.источник
IEnumerator<Tuple<TKey1, TKey2>>
здесь. НетIEnumerator<KeyValuePair<TKey1, TKey2>>
, поэтому я думаю, что не могу сделать это с моей функцией GetEnumerator. Я правильно понял?Я создал такой класс, используя классы коллекции C5.
источник
Еще одно расширение принятого ответа. Он реализует IEnumerable, поэтому с ним можно использовать foreach. Я понимаю, что с реализацией IEnumerable есть больше ответов, но здесь используются структуры, поэтому он удобен для сборщика мусора . Это особенно полезно в движке Unity (проверено профилировщиком).
источник
Немного поздно, но вот реализация, которую я написал некоторое время назад. Он обрабатывает несколько интересных пограничных случаев, например, когда ключ переопределяет проверку равенства для выполнения частичного равенства. Это приводит к хранению основного словаря,
A => 1
но к обратному хранению1 => A'
.Вы получаете доступ к обратному словарю через
Inverse
свойство.Исходники и тесты на github.
источник