.NET字典中的重复键?

.NET基类库中是否有允许使用重复键的字典类? 我find的唯一解决scheme是创build一个类,例如:

Dictionary<string, List<object>> 

但是这实际上使用起来很刺激。 在Java中,我相信一个MultiMap可以完成这个任务,但在.NET中找不到一个模拟器。

如果您使用的是.NET 3.5,请使用Lookup类。

编辑:您通常使用Enumerable.ToLookup创build一个Lookup 。 这确实假设你以后不需要改变它 – 但是我通常发现这已经足够好了。

如果这适合你,我不认为有什么在框架中会有所帮助 – 并使用字典是一样好,因为:(

List类实际上对于包含重复项的键/值集合非常适用,您希望遍历集合。 例:

 List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>(); // add some values to the collection here for (int i = 0; i < list.Count; i++) { Print(list[i].Key, list[i].Value); } 

这是List <KeyValuePair <string,string>>的一种方法

 public class ListWithDuplicates : List<KeyValuePair<string, string>> { public void Add(string key, string value) { var element = new KeyValuePair<string, string>(key, value); this.Add(element); } } var list = new ListWithDuplicates(); list.Add("k1", "v1"); list.Add("k1", "v2"); list.Add("k1", "v3"); foreach(var item in list) { string x = string.format("{0}={1}, ", item.Key, item.Value); } 

输出k1 = v1,k1 = v2,k1 = v3

如果使用string作为键和值,则可以使用System.Collections.Specialized.NameValueCollection ,它将通过GetValues(string key)方法返回一个string值数组。

我刚刚遇到PowerCollections库,其中包括一个名为MultiDictionary的类。 这整齐地包装这种types的function。

关于使用Lookup的非常重要的注意事项:

您可以通过对实现IEnumerable(T)的对象调用ToLookup来创buildLookup(TKey, TElement)的实例。

没有公共构造函数来创build一个Lookup(TKey, TElement)的新实例Lookup(TKey, TElement) 。 此外, Lookup(TKey, TElement)对象是不可变的,也就是说,在创build后,您不能在Lookup(TKey, TElement)对象中添加或移除元素或键。

(来自MSDN)

我认为这将成为大多数用途的展示瓶颈。

我认为像List<KeyValuePair<object, object>>会做的工作。

如果您使用> = .NET 4,则可以使用Tuple Class:

 // declaration var list = new List<Tuple<string, List<object>>>(); // to add an item to the list var item = Tuple<string, List<object>>("key", new List<object>); list.Add(item); // to iterate foreach(var i in list) { Console.WriteLine(i.Item1.ToString()); } 

看看C5的 HashBag类。

回答原来的问题。 像Dictionary<string, List<object>>是在Code Project MultiMap类中实现的。

你可以find更多的信息到下面的链接: http : //www.codeproject.com/KB/cs/MultiKeyDictionary.aspx

NameValueCollection在一个键(也是一个string)下支持多个string值,但这是我知道的唯一例子。

当我遇到需要这种function的情况时,我倾向于创build类似于您示例中的构造的构造。

当使用List<KeyValuePair<string, object>>选项时,可以使用LINQ来进行search:

 List<KeyValuePair<string, object>> myList = new List<KeyValuePair<string, object>>(); //fill it here var q = from a in myList Where a.Key.Equals("somevalue") Select a.Value if(q.Count() > 0){ //you've got your value } 

“滚动自己的”版本的允许“重复密钥”条目的字典很容易。 这是一个粗略简单的实现。 您可能要考虑添加基本上大部分(如果不是全部)对IDictionary<T>

 public class MultiMap<TKey,TValue> { private readonly Dictionary<TKey,IList<TValue>> storage; public MultiMap() { storage = new Dictionary<TKey,IList<TValue>>(); } public void Add(TKey key, TValue value) { if (!storage.ContainsKey(key)) storage.Add(key, new List<TValue>()); storage[key].Add(value); } public IEnumerable<TKey> Keys { get { return storage.Keys; } } public bool ContainsKey(TKey key) { return storage.ContainsKey(key); } public IList<TValue> this[TKey key] { get { if (!storage.ContainsKey(key)) throw new KeyNotFoundException( string.Format( "The given key {0} was not found in the collection.", key)); return storage[key]; } } } 

一个关于如何使用它的简单例子:

 const string key = "supported_encodings"; var map = new MultiMap<string,Encoding>(); map.Add(key, Encoding.ASCII); map.Add(key, Encoding.UTF8); map.Add(key, Encoding.Unicode); foreach (var existingKey in map.Keys) { var values = map[existingKey]; Console.WriteLine(string.Join(",", values)); } 

你的意思是一致的,而不是一个实际的重复? 否则散列表将无法工作。

一致意味着两个单独的密钥可以散列到等价值,但密钥不相等。

例如:说你的散列表的散列函数只是hashval =键模3,1和4都映射到1,但是是不同的值。 这就是你列表的想法发挥的地方。

当您需要查找1时,将该值散列为1,遍历该列表,直到findKey = 1。

如果允许插入重复键,则无法区分哪些键映射到哪些值。

我偶然发现了这个post寻找相同的答案,并没有发现,所以我用一个字典列表搭build了一个简单的示例解决scheme,覆盖[]运算符添加一个新的字典,当其他人有一个给定键(set),并返回一个值列表(get)。
这是丑陋和低效率,它只能获取/设置的关键,它总是返回一个列表,但它的工作原理:

  class DKD { List<Dictionary<string, string>> dictionaries; public DKD(){ dictionaries = new List<Dictionary<string, string>>();} public object this[string key]{ get{ string temp; List<string> valueList = new List<string>(); for (int i = 0; i < dictionaries.Count; i++){ dictionaries[i].TryGetValue(key, out temp); if (temp == key){ valueList.Add(temp);}} return valueList;} set{ for (int i = 0; i < dictionaries.Count; i++){ if (dictionaries[i].ContainsKey(key)){ continue;} else{ dictionaries[i].Add(key,(string) value); return;}} dictionaries.Add(new Dictionary<string, string>()); dictionaries.Last()[key] =(string)value; } } } 

我使用的方式只是一个

Dictionary<string, List<string>>

这样你就有一个键保存一个string列表。

例:

 List<string> value = new List<string>(); if (dictionary.Contains(key)) { value = dictionary[key]; } value.Add(newValue); 

你可以定义一个方法来构build一个复合string键,每一个你想要使用字典的地方你都必须使用这个方法来构build你的键,例如:

 private string keyBuilder(int key1, int key2) { return string.Format("{0}/{1}", key1, key2); } 

使用:

 myDict.ContainsKey(keyBuilder(key1, key2)) 

这也是可能的:

 Dictionary<string, string[]> previousAnswers = null; 

这样,我们可以拥有唯一的键。 希望这对你有用。

重复键将打破词典的整个合约。 在字典中,每个键都是唯一的,并映射到单个值。 如果你想把一个对象连接到任意数量的附加对象,最好的办法可能就是类似于DataSet(用一般的术语来说)。 把你的钥匙放在一列,你的价值在另一列。 这比字典慢得多,但是这是你失去散列关键对象的能力的折衷。

你可以添加不同的情况下相同的密钥,如:

KEY1
键1
KEY1
KEY1
KEY1
KEY1

我知道是假的答案,但为我工作。