Es fácil obtener el valor de una clave de un Diccionario genérico .NET:
Dictionary<int, string> greek = new Dictionary<int, string>();
greek.Add(1, "Alpha");
greek.Add(2, "Beta");
string secondGreek = greek[2]; // Beta
Pero tratar de obtener un valor dado a las claves no es tan sencillo porque podría haber varias claves:
int[] betaKeys = greek.WhatDoIPutHere("Beta"); // expecting single 2
int[]
cuando espera un valor único?Respuestas:
Bien, aquí está la versión bidireccional múltiple:
fuente
Como todos han dicho, no hay mapeo dentro de un diccionario de valor a clave.
Me acabo de dar cuenta de que querías asignar desde el valor a varias claves. Dejo esta solución aquí para la versión de valor único, pero luego agregaré otra respuesta para un mapa bidireccional de entradas múltiples.
El enfoque normal a seguir aquí es tener dos diccionarios: uno de mapeo en un sentido y otro en el otro. Encapsúlelos en una clase separada y calcule lo que quiere hacer cuando tenga una clave o valor duplicado (por ejemplo, lanzar una excepción, sobrescribir la entrada existente o ignorar la nueva entrada). Personalmente, probablemente elegiría una excepción: hace que el comportamiento de éxito sea más fácil de definir. Algo como esto:
fuente
Add
llamadas del diccionario fallará, pero si es la segunda, entonces tenemos el sistema en un estado confuso. A mi manera, todavía tienes una colección consistente después de la excepción.Los diccionarios en realidad no están destinados a funcionar así, porque si bien la unicidad de las claves está garantizada, la unicidad de los valores no. Entonces, si tuvieras
¿Qué esperarías obtener
greek.WhatDoIPutHere("Alpha")
?Por lo tanto, no puede esperar que algo como esto se incorpore al marco. Necesitaría su propio método para sus propios usos únicos --- ¿desea devolver una matriz (o
IEnumerable<T>
)? ¿Desea lanzar una excepción si hay varias claves con el valor dado? ¿Qué pasa si no hay ninguno?Personalmente iría por un enumerable, así:
fuente
Quizás la forma más fácil de hacerlo, sin Linq, puede ser recorrer los pares:
Si tuviera Linq, podría haberlo hecho fácilmente de esta manera:
fuente
var
es una característica del lenguaje, no una característica del marco. Puede usar la fusión nula de C # -6.0 y seguir apuntando a CF-2.0 si realmente lo desea.Un diccionario no guarda un hash de los valores, solo las claves, por lo que cualquier búsqueda sobre él utilizando un valor llevará al menos un tiempo lineal. Su mejor opción es simplemente iterar sobre los elementos en el diccionario y realizar un seguimiento de las claves coincidentes o cambiar a una estructura de datos diferente, tal vez mantener dos claves de asignación de diccionario-> valor y valor-> Lista_de_claves. Si hace lo último, cambiará el almacenamiento por velocidad de búsqueda. No tomaría mucho convertir el ejemplo de @Cybis en una estructura de datos de este tipo.
fuente
Como quería un Diccionario BiDireccional completo (y no solo un Mapa), agregué las funciones que faltaban para convertirlo en una clase IDictionary compatible. Esto se basa en la versión con pares clave-valor únicos. Aquí está el archivo si lo desea (la mayoría del trabajo fue a través de XMLDoc):
fuente
revisado: está bien tener algún tipo de hallazgo que necesitaría algo más que un diccionario, ya que si lo piensa, el diccionario son claves unidireccionales. es decir, los valores pueden no ser únicos
Dicho esto, parece que está usando C # 3.0, por lo que es posible que no tenga que recurrir al bucle y podría usar algo como:
fuente
La clase de diccionario no está optimizada para este caso, pero si realmente quería hacerlo (en C # 2.0), puede hacer lo siguiente:
Prefiero la solución LINQ por elegancia, pero esta es la forma 2.0.
fuente
¿No puedes crear una subclase de Diccionario que tenga esa funcionalidad?
EDITAR: Lo siento, no obtuve el código correcto la primera vez.
fuente
La solución de diccionario bidireccional "simple" propuesta aquí es compleja y puede ser difícil de entender, mantener o ampliar. También la pregunta original pedía "la clave para un valor", pero claramente podría haber varias claves (desde entonces he editado la pregunta). Todo el enfoque es bastante sospechoso.
Cambios de software. Escribir código que sea fácil de mantener debería tener prioridad sobre otras soluciones complejas "inteligentes". La forma de recuperar las claves de los valores en un diccionario es hacer un bucle. Un diccionario no está diseñado para ser bidireccional.
fuente
int
valores porstring
clave, a continuación, el diccionario se puede definir como sigue:Dictionary<string, List<int>>
.Dictionary
no no ofrecen una capacidad bidireccional. Por lo tanto, si todo lo que tiene es un estándarDictionary
y desea encontrar la (s) clave (s) asociada (s) con un valor específico, ¡debe iterar! Sin embargo, para los diccionarios "grandes", la iteración puede resultar en un bajo rendimiento. Tenga en cuenta que la respuesta que yo mismo ofrecí se basa en la iteración (a través de LINQ). Si su inicialDictionary
no está sujeta a cambios adicionales, puede construir una inversiónDictionary
una vez para acelerar las búsquedas inversas.Use LINQ para hacer una
Dictionary<K, V>
búsqueda inversa . Pero tenga en cuenta que los valores en susDictionary<K, V>
valores pueden no ser distintos.Demostración:
Rendimiento esperado:
fuente
fuente
Como un giro de la respuesta aceptada ( https://stackoverflow.com/a/255638/986160 ) suponiendo que las claves se asociarán con valores de señal en el diccionario. Similar a ( https://stackoverflow.com/a/255630/986160 ) pero un poco más elegante. La novedad es que la clase consumidora se puede usar como una alternativa de enumeración (pero también para cadenas) y que el diccionario implementa IEnumerable.
Y como clase consumidora podrías tener
fuente
Entonces la solución del laico
Se podría escribir una función similar a la siguiente para crear dicho diccionario:
fuente