2010-07-07 11 views
7

¿Existe una estructura de datos C# para asignar claves a valores múltiples? Tengo una colección de artículos que quiero poner por nombre; sin embargo, el nombre no es único. Hashtable y Dictionary solo permiten claves únicas. La búsqueda parece cercana a lo que quiero; sin embargo, no es mutable.¿Existe una estructura de datos C# para asignar claves a múltiples valores?

¿Existe una estructura de datos integrada que me falta o necesito crear una yo mismo?

+1

¿Cómo va a conseguir la valora si el nombre no es único y eso es lo que espera hacer su búsqueda? –

+0

Supongo que devolvería un IEnumerable o equivalente. – user171197

Respuesta

8

Lo que estás buscando es un multimap.

Es posible que desee echar un vistazo a la answer to this question.

Es posible que también desee consultar el C5 Generic Collection library, que es gratuito y tiene una implementación de un multimapa.

Si tienes ganas de rodar su propio, un lugar sencillo para empezar es un diccionario de listas:

Dictionary<TKey,List<TValue>> 

Sin embargo, no se puede añadir a un diccionario como la forma normal. Primero debe verificar si la clave ya existe y, de ser así, buscar el valor (lista) y agregarlo. De lo contrario, debe crear la lista y completarla con un valor.

Si usted está tan inclinado, sugeriría que considerar el uso de un conjunto de métodos de extensión para simplificar la opción Agregar/Quitar operaciones:

public static class MultimapExt 
{ 
    public static void Add<TKey,TValue>( 
     this Dictionary<TKey,List<TValue>> dictionary, TKey key, TValue value) 
    { 
     List<TValue> valueList; 
     if(!dictionary.TryGetValue(key, out valueList) 
     { 
      valueList = new List<TValue>(); 
      dictionary.Add(key, valueList); 
     } 
     valueList.Add(value); 
    } 

    public static void Remove<TKey,TValue>(
     this Dictionary<TKey,List<TValue>> dictionary, TKey key, TValue value) 
    { 
     List<TValue> valueList; 
     if(dictionary.TryGetValue(key, out valueList)) 
     { 
      valueList.Remove(value); 
      if(valueList.Count == 0) 
       dictionary.Remove(key); 
     } 
    } 
} 
+0

Esto parece lo que estoy buscando. ¡Gracias! Solo desearía que estuviera integrado en el marco. – user171197

+0

Necesita agregar valueList a su diccionario en su método Agregar. –

+1

Iría con algo un poco más flexible: 'Agregar (esta IDictionary , tecla TKey, valor de TValue) donde TCollection: ICollection '. De esta forma, no se restringe a una tienda interna de tipo 'List ' solamente (o de 'Dictionary ' tampoco, para el caso). –

0

¿Qué pasa con el uso de un diccionario para IList<YOUR_VALUE_TYPE>?

+0

Esto es lo que probablemente haría si lo estuviera implementando yo mismo. Me preguntaba si había algo incorporado. – user171197

2

LBushkin's answer es una buena opción. Puede que sea un poco más flexible, sin embargo, mediante la eliminación de la restricción innecesario el uso de Dictionary<TKey, List<TValue>> (de esta manera también se puede utilizar, por ejemplo, un SortedDictionary<TKey, LinkedList<TValue>>) a través de algunas limitaciones genéricas cuidadosamente elegidos:

public static class MultimapExt 
{ 
    public static void Add<TKey, TValue, TCollection>( 
     this IDictionary<TKey, TCollection> dictionary, 
     TKey key, 
     TValue value 
    ) where TCollection : ICollection<TValue>, new() 
    { 
     TCollection collection; 
     if(!dictionary.TryGetValue(key, out collection) 
     { 
      collection = new TCollection(); 
      dictionary.Add(key, collection); 
     } 

     collection.Add(value); 
    } 

    public static bool Remove<TKey, TValue, TCollection>(
     this IDictionary<TKey, TCollection> dictionary, 
     TKey key, 
     TValue value 
    ) where TCollection : ICollection<TValue> 
    { 
     TCollection collection; 
     if(dictionary.TryGetValue(key, out collection)) 
     { 
      bool removed = collection.Remove(value); 

      if(collection.Count == 0) 
       dictionary.Remove(key); 

      return removed; 
     } 

     return false; 
    } 
} 
+0

Su mejora definitivamente es buena, es útil poder desacoplar el comportamiento de la administración de la colección. Sin embargo, en la práctica, puede tener sentido que nuestras dos soluciones migren a una implementación real de 'IDictionary <> 'en lugar de vivir solo como métodos de extensión. : D – LBushkin

+0

@LBushkin: No podría estar más de acuerdo. Pero son buenos para fines ilustrativos, creo. –

Cuestiones relacionadas