Estoy buscando una clase de diccionario 1 a 1 bidireccional genérica en C # (2), es decir. a BiDictionaryOneToOne<T, S>
que está garantizado para contener solo uno de cada valor y clave (hasta RefEquals de todos modos), y que se puede buscar utilizando la clave o el valor. ¿Alguien sabe de uno, o debería implementarlo yo mismo? No puedo creer que sea la primera persona en necesitar esto ...
Hay un BiDictionary en las respuestas a esta pregunta , pero no es para elementos únicos (y tampoco implementa RemoveByFirst (T t) o RemoveBySecond (S s)).
¡Gracias!
c#
.net
collections
Joel en Gö
fuente
fuente
Respuestas:
OK, aquí está mi intento (basado en el de Jon, gracias), archivado aquí y abierto para mejoras:
fuente
Una implementación más completa del diccionario bidireccional:
Dictionary<TKey,TValue>
(excepto las interfaces de infraestructura):IDictionary<TKey, TValue>
IReadOnlyDictionary<TKey, TValue>
IDictionary
ICollection<KeyValuePair<TKey, TValue>>
(esta y las siguientes son las interfaces base de las anteriores)ICollection
IReadOnlyCollection<KeyValuePair<TKey, TValue>>
IEnumerable<KeyValuePair<TKey, TValue>>
IEnumerable
SerializableAttribute
.DebuggerDisplayAttribute
(con información de recuento) yDebuggerTypeProxyAttribute
(para mostrar pares clave-valor en relojes).IDictionary<TValue, TKey> Reverse
propiedad y también implementa todas las interfaces mencionadas anteriormente. Todas las operaciones en cualquiera de los diccionarios modifican ambos.Uso:
El código está disponible en mi marco privado en GitHub: BiDictionary (TFirst, TSecond) .cs ( enlace permanente , búsqueda ).
Copiar:
fuente
item.Reverse
líneas. ¿Algún requisito de versión en particular?KeyValuePairExts
clase al final del fragmento de código.La pregunta a la que hace referencia también muestra una implementación uno a uno en esta respuesta . Agregar RemoveByFirst y RemoveBySecond sería trivial, al igual que implementar interfaces adicionales, etc.
fuente
Esta es la misma que la respuesta aceptada, pero también proporcioné
Update
métodos y, sobre todo, un poco más desarrollado:Similar a mi respuesta aquí
Algunas cosas a tener en cuenta:
Solo he implementado
IEnumerable<>
. No creo queICollection<>
tenga sentido aquí, ya que los nombres de los métodos podrían ser muy diferentes para esta estructura de colección especial. Depende de usted decidir qué debe ir dentroIEnumerable<>
. Así que ahora también tiene la sintaxis del inicializador de colección, comoHe intentado lanzar algunas excepciones extrañas aquí y allá, solo para la integridad de los datos. Solo para estar más seguro y saber si alguna vez mi código tiene errores.
Rendimiento: puede buscar
Value
con cualquiera de losKeys
mediosGet
yContains
métodos que requieren solo 1 búsqueda (O (1)).Add
requiere 2 búsquedas y 2 adiciones.Update
requiere 1 búsqueda y 2 adiciones.Remove
toma 3 búsquedas. Todo similar a la respuesta aceptada.fuente
IEnumerator<Tuple<TKey1, TKey2>>
aquí. NoIEnumerator<KeyValuePair<TKey1, TKey2>>
, así que creo que no puedo hacer eso con mi función GetEnumerator. ¿Te entendí correctamente?He creado una clase de este tipo, utilizando clases de colección C5.
fuente
Otra extensión de la respuesta aceptada. Implementa IEnumerable para que uno pueda usar foreach con eso. Me doy cuenta de que hay más respuestas con la implementación de IEnumerable, pero esta usa estructuras, por lo que es compatible con el recolector de basura . Esto es especialmente útil en el motor Unity (verificado con el generador de perfiles).
fuente
Un poco tarde, pero aquí hay una implementación que escribí hace un tiempo. Maneja algunos casos extremos interesantes, como cuando la clave anula la verificación de igualdad para realizar una igualdad parcial. Esto da como resultado el almacenamiento del diccionario principal
A => 1
pero el almacenamiento inverso1 => A'
.Se accede al diccionario inverso a través de la
Inverse
propiedad.Fuente original y pruebas en github.
fuente