多值字典?

有人知道MultiValueDictionary的良好实现吗? 基本上,我想要一些允许每个键有多个值的东西。 我希望能够做类似的事情

 dict.Add(key, val); 

如果密钥尚不存在,它将添加它,如果它存在,它将只添加该密钥的另一个值。 我只是要迭代它,所以我真的不关心其他检索方法。

它不存在,但您可以从Dictionary和List中快速构建一个:

 class MultiDict // no (collection) base class { private Dictionary> _data = new Dictionary>(); public void Add(TKey k, TValue v) { // can be a optimized a little with TryGetValue, this is for clarity if (_data.ContainsKey(k)) _data[k].Add(v) else _data.Add(k, new List() { v}) ; } // more members } 

微软刚刚在NuGet上添加了一个官方预发布版本,你正在寻找什么(称为MultiDictionary): https ://www.nuget.org/packages/Microsoft.Experimental.Collections/

有关使用情况和更多详细信息,请访问官方MSDN博客文章: http : //blogs.msdn.com/b/dotnet/archive/2014/06/20/would-you-like-a-multidictionary.aspx

我是此软件包的开发人员,如果您对性能或任何问题有任何疑问,请在此处或MSDN上告诉我。

希望有所帮助。

您可以从列表字典中轻松制作一个:

 public class MultiValueDictionary : Dictionary> { public void Add(Key key, Value value) { List values; if (!this.TryGetValue(key, out values)) { values = new List(); this.Add(key, values); } values.Add(value); } } 

您始终可以使用Tuple作为第二个通用参数:

 var dict = new Dictionary>(); dict.Add("key", new Tuple("string1", 4, new Object())); 

或者甚至将通用List作为第二个通用参数:

 var dict = new Dictionary>(); 

这将允许您将多个值绑定到单个键。

为了便于使用,您可以创建一个扩展方法,以检查是否存在密钥并添加到列表中。

这是我写的一篇你可以使用的。

它有一个inheritance自Dictionary的“MultiValueDictionary”类。

它还有一个扩展类,允许您在值类型为IList的任何Dictionary上使用特殊的Addfunction; 这样你就不会被迫使用自定义类,如果你不想这样做的话。

 public class MultiValueDictionary : Dictionary> { ///  /// Hide the regular Dictionary Add method ///  new private void Add(KeyType key, List value) { base.Add(key, value); } ///  /// Adds the specified value to the multi value dictionary. ///  /// The key of the element to add. /// The value of the element to add. The value can be null for reference types. public void Add(KeyType key, ValueType value) { //add the value to the dictionary under the key MultiValueDictionaryExtensions.Add(this, key, value); } } public static class MultiValueDictionaryExtensions { ///  /// Adds the specified value to the multi value dictionary. ///  /// The key of the element to add. /// The value of the element to add. The value can be null for reference types. public static void Add(this Dictionary thisDictionary, KeyType key, ValueType value) where ListType : IList, new() { //if the dictionary doesn't contain the key, make a new list under the key if (!thisDictionary.ContainsKey(key)) { thisDictionary.Add(key, new ListType()); } //add the value to the list at the key index thisDictionary[key].Add(value); } } 

您可以使用PowerCollections中的 MultiDictionary类。

它返回ICollection {TValue}以获取所要求的密钥。

只需将0.02美元添加到解决方案集合中:

我在2011年有同样的需求,并创建了一个MultiDictionary其中包含了所有.NET接口的完整实现。 这包括返回标准KeyValuePair枚举数,并支持IDictionary.Values属性,提供实际值的集合(而不是ICollection> )。

这样,它与.NET集合类的其余部分完全吻合。 我还定义了一个IMultiDictionary接口来访问特定于这种字典的操作:

 public interface IMultiDictionary : IDictionary>, IDictionary, ICollection>, IEnumerable>, IEnumerable { /// Adds a value into the dictionary /// Key the value will be stored under /// Value that will be stored under the key void Add(TKey key, TValue value); /// Determines the number of values stored under a key /// Key whose values will be counted /// The number of values stored under the specified key int CountValues(TKey key); ///  /// Removes the item with the specified key and value from the dictionary ///  /// Key of the item that will be removed /// Value of the item that will be removed /// True if the item was found and removed bool Remove(TKey key, TValue value); /// Removes all items of a key from the dictionary /// Key of the items that will be removed /// The number of items that have been removed int RemoveKey(TKey key); } 

它可以在.NET 2.0以上的任何版本上编译,到目前为止我已经将它部署在Xbox 360,Windows Phone 7,Linux和Unity 3D上。 还有一个完整的unit testing套件,涵盖了代码的每一行。

该代码根据通用公共许可证进行许可 (简称:任何内容,但必须发布对代码库的代码的错误修复),并且可以在我的Subversion存储库中找到。

然而, 这是我尝试使用ILookup和一个内部KeyedCollection 。 确保key属性是不可变的。
Cross发布在这里 。

 public class Lookup : Collection, ILookup { public Lookup(Func keyForItem) : base((IList)new Collection(keyForItem)) { } new Collection Items => (Collection)base.Items; public IEnumerable this[TKey key] => Items[key]; public bool Contains(TKey key) => Items.Contains(key); IEnumerator> IEnumerable>.GetEnumerator() => Items.GetEnumerator(); class Collection : KeyedCollection { Func KeyForItem { get; } public Collection(Func keyForItem) => KeyForItem = keyForItem; protected override TKey GetKeyForItem(Grouping item) => item.Key; public void Add(TElement item) { var key = KeyForItem(item); if (Dictionary != null && Dictionary.TryGetValue(key, out var collection)) collection.Add(item); else Add(new Grouping(key) { item }); } public bool Remove(TElement item) { var key = KeyForItem(item); if (Dictionary != null && Dictionary.TryGetValue(key, out var collection) && collection.Remove(item)) { if (collection.Count == 0) Remove(key); return true; } return false; } } class Grouping : Collection, IGrouping { public Grouping(TKey key) => Key = key; public TKey Key { get; } } } 

这应该做到现在……

 public class MultiValueDictionary : IEnumerable> { private Dictionary> _dict = new Dictionary>(); public void Add(TKey key, TValue value) { if(!_dict.ContainsKey(key)) _dict[key] = new LinkedList(); _dict[key].AddLast(value); } public IEnumerator> GetEnumerator() { foreach (var list in _dict) foreach (var value in list.Value) yield return new KeyValuePair(list.Key, value); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } 

自定义类型的替代方法可以是通用扩展,在未找到时添加键和值:

 public static V getValue(this IDictionary d, K key) where V : new() { V v; if (!d.TryGetValue(key, out v)) { v = new V(); d.Add(key, v); } return v; } 

样品用途:

 var d = new Dictionary>(); d.getValue(1).AddLast(2);