2010-01-02 31 views
4

.NET 3.5發佈之前,我用如何修改C#4.0中的ILookup對象?

Dictionary<TKey, List<TValue>> 

用於保存數據。但是我發現.NET 3.5提供了新的集合類型,它是可以表示我的舊複雜數據類型的ILookup類。

我總是通過使用LINQ擴展方法(ToLookup方法)創建ILookup對象。但是我不知道如何修改ILookup對象。

可能嗎?或者我需要使用聯合方法創建並再次調用ToLookup方法。

感謝,

回答

4

你不這樣做,這是不可改變的。你已經列出了兩個合理的選項;要麼使用子集合的字典,要麼繼續創建新的查找。

4

以下是可以操縱的ILookup的實施示例。它圍繞着List的元素的Dictionary。它是完全通用的。我想不出一個更好的名字。 :)

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

正如mquander所述,查找是不可變的。但是,您可以使用其他或刪除的值構建新的查找。

// 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);