2010-01-02 5 views
4

Avant .NET 3.5 est sorti, j'utiliseComment modifier l'objet ILookup dans C# 4.0?

Dictionary<TKey, List<TValue>> 

pour contenir des données. Mais je viens de découvrir que .NET 3.5 fournit un nouveau type de collection qui est la classe ILookup qui peut représenter mon ancien type de données complexe.

Je crée toujours l'objet ILookup à l'aide de la méthode d'extension LINQ (méthode ToLookup). Mais je ne sais pas comment modifier l'objet ILookup.

Est-ce possible? Ou je dois créer en utilisant la méthode d'union et appeler à nouveau la méthode ToLookup.

Merci,

Répondre

4

Vous ne le faites pas, il est immuable. Vous avez énuméré les deux options raisonnables; soit pour utiliser un dictionnaire de sous-collections ou pour continuer à créer de nouvelles recherches.

4

Voici un exemple d'implémentation de ILookup pouvant être manipulée. Il entoure un Dictionary de List des éléments. C'est complètement générique. Je ne pouvais pas penser à un meilleur nom. :)

public class LookupDictionary<TKey, TElement> : ILookup<TKey, TElement> 
{ 
    private Dictionary<TKey, List<TElement>> _dicLookup = new Dictionary<TKey, List<TElement>>(); 

    public LookupDictionary() 
    { 

    } 

    public LookupDictionary(ILookup<TKey, TElement> a_lookup) 
    { 
     foreach (var grouping in a_lookup) 
     { 
      foreach (var element in grouping) 
       AddElement(grouping.Key, element); 
     } 
    } 

    public IEnumerable<TElement> AllElements 
    { 
     get 
     { 
      return (from key in _dicLookup.Keys 
        select _dicLookup[key]) 
        .SelectMany(list => list); 
     } 
    } 

    public int Count 
    { 
     get 
     { 
      return AllElements.Count(); 
     } 
    } 

    public IEnumerable<TElement> this[TKey a_key] 
    { 
     get 
     { 
      List<TElement> list; 
      if (_dicLookup.TryGetValue(a_key, out list)) 
       return list; 

      return new TElement[0]; 
     } 
    } 

    public bool Contains(TKey a_key) 
    { 
     return _dicLookup.ContainsKey(a_key); 
    } 

    public void Add(TKey a_key, TElement a_element) 
    { 
     AddElement(a_key, a_element); 
    } 

    public void RemoveKey(TKey a_key) 
    { 
     _dicLookup.Remove(a_key); 
    } 

    public IEnumerator<IGrouping<TKey, TElement>> GetEnumerator() 
    { 
     return GetGroupings().GetEnumerator(); 
    } 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return (GetGroupings() as System.Collections.IEnumerable).GetEnumerator(); 
    } 

    private void AddElement(TKey a_key, TElement a_element) 
    { 
     List<TElement> list; 

     if (!_dicLookup.TryGetValue(a_key, out list)) 
     { 
      list = new List<TElement>(); 
      _dicLookup.Add(a_key, list); 
     } 

     list.Add(a_element); 
    } 

    private IEnumerable<IGrouping<TKey, TElement>> GetGroupings() 
    { 
     return from key in _dicLookup.Keys 
       select new LookupDictionaryGrouping<TKey, TElement> 
       { 
        Key = key, 
        Elements = _dicLookup[key] 
       } as IGrouping<TKey, TElement>; 
    } 
} 

public class LookupDictionaryGrouping<TKey, TElement> : IGrouping<TKey, TElement> 
{ 
    public TKey Key 
    { 
     get; 
     set; 
    } 

    public IEnumerable<TElement> Elements 
    { 
     get; 
     set; 
    } 

    public IEnumerator<TElement> GetEnumerator() 
    { 
     return Elements.GetEnumerator(); 
    } 


    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return (Elements as System.Collections.IEnumerable).GetEnumerator(); 
    } 
} 
0

Comme mquander mentionné, la recherche est immuable. Cependant, vous pouvez créer une nouvelle recherche avec des valeurs supplémentaires ou supprimées.

// Add a new value 
myLookup = myLookup 
    .SelectMany(l => l.Select(v => new {l.Key, Value = v})) 
    .Union(new[] {new {Key = myNewKey, Value = myNewValue}}) 
    .ToLookup(a => a.Key, a => a.Value); 

// Remove an old value 
myLookup = myLookup 
    .SelectMany(l => l.Select(v => new {l.Key, Value = v})) 
    .Where(a => a.Value != myOldValue) 
    .ToLookup(a => a.Key, a => a.Value);