2010-07-07 49 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

相关问题