2010-07-07 70 views
7

是否有C#數據結構將鍵映射到多個值?我有一系列我想按名稱輸入的項目;然而,這個名字並不是唯一的。散列表和字典只允許唯一的鍵。查找似乎接近我想要的;但是,它不可變。是否有C#數據結構將鍵映射到多個值?

有沒有內置的數據結構,我失蹤或我需要自己建立一個?

+1

您將如何獲得如果這個名字不是唯一的,那麼這個值就是值得注意的,這就是你希望查找的內容? – 2010-07-07 18:43:43

+0

我會假設它會返回一個IEnumerable或等價的。 – user171197 2010-07-07 18:49:20

回答

8

你在找什麼是multimap。你可能想看看answer to this question

您可能還想看看C5 Generic Collection library,它是免費的,並且有一個multimap的實現。

如果你喜歡滾動您自己,一個簡單的地方開始是列表的字典:

Dictionary<TKey,List<TValue>> 

但是,你不能添加到這樣一本詞典的正常方式。你必須首先檢查密鑰是否已經存在,如果是的話,獲取值(列表)並添加到它。否則,您需要創建列表並使用值填充它。

如果你願意的話,我建議你考慮使用一套擴展的方法來簡化添加/刪除操作:

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

這看起來我在找什麼。謝謝!我只是希望它被構建到框架中。 – user171197 2010-07-07 18:50:48

+0

您需要在您的Add方法中將valueList添加到您的字典中。 – 2010-07-07 19:43:46

+1

我會更靈活一些:添加(此IDictionary ,TKey鍵,TValue值),其中TCollection:ICollection '。這樣,你就不會限制自己到一個只有'List '類型的內部存儲器(或者只有'Dictionary ')。 – 2010-07-07 20:08:13

0

什麼用字典來IList<YOUR_VALUE_TYPE>

+0

如果我自己實施它,我可能會這樣做。我只是想知道是否有內置的東西。 – user171197 2010-07-07 18:50:18

2

LBushkin's answer是個不錯的選擇。你可以把它多一點靈活,不過,通過消除不必要的限制通過一些精心挑選的一般限制使用Dictionary<TKey, List<TValue>>(這樣你也可以使用,比如說,一個SortedDictionary<TKey, LinkedList<TValue>>):

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

你的增強功能絕對是一個很好的增強功能 - 它能夠分離收集管理行爲是有用的。但實際上,我們的兩個解決方案都可以遷移到實際的IDictionary <>實現中,而不僅僅是擴展方法。 :D – LBushkin 2010-07-07 20:29:14

+0

@LBushkin:我完全同意。但是,我認爲它們對於說明性目的而言是很好的。 – 2010-07-07 20:52:59

相關問題