Multi Value Dictionary?

后端 未结 10 1857
萌比男神i
萌比男神i 2020-11-27 20:45

Anyone know of a good implementation of a MultiValueDictionary? Basically, I want something that allows multiple values per key. I want to be able to do somethi

相关标签:
10条回答
  • 2020-11-27 21:41

    Just to add my $0.02 to the collection of solutions:

    I had the same need back in 2011 and created a MultiDictionary with a pedantically complete implementation of all the .NET interfaces. That includes enumerators that return a standard KeyValuePair<K, T> and support for the IDictionary<K, T>.Values property providing a collection of actual values (instead of an ICollection<ICollection<T>>).

    That way, it fits in neatly with the rest of the .NET collection classes. I also defined an IMultiDictionary<K, T> interface to access operations that are particular to this kind of dictionary:

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

    It can be compiled on anything from .NET 2.0 upwards and so far I've deployed it on the Xbox 360, Windows Phone 7, Linux and Unity 3D. There's also a complete unit test suite covering every single line of the code.

    The code is licensed under the Common Public License (short: anything goes, but bug fixes to the library's code have to published) and can be found in my Subversion repository.

    0 讨论(0)
  • 2020-11-27 21:46

    Here's one I wrote a while back that you can use.

    It has a "MultiValueDictionary" class that inherits from Dictionary.

    It also has an extension class that allows you to use the special Add functionality on any Dictionary where the value type is an IList; that way you're not forced to use the custom class if you don't want to.

    public class MultiValueDictionary<KeyType, ValueType> : Dictionary<KeyType, List<ValueType>>
    {
        /// <summary>
        /// Hide the regular Dictionary Add method
        /// </summary>
        new private void Add(KeyType key, List<ValueType> value)
        {            
            base.Add(key, value);
        }
    
        /// <summary>
        /// Adds the specified value to the multi value dictionary.
        /// </summary>
        /// <param name="key">The key of the element to add.</param>
        /// <param name="value">The value of the element to add. The value can be null for reference types.</param>
        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
    {
        /// <summary>
        /// Adds the specified value to the multi value dictionary.
        /// </summary>
        /// <param name="key">The key of the element to add.</param>
        /// <param name="value">The value of the element to add. The value can be null for reference types.</param>
        public static void Add<KeyType, ListType, ValueType>(this Dictionary<KeyType, ListType> thisDictionary, 
                                                             KeyType key, ValueType value)
        where ListType : IList<ValueType>, 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);
        }
    }
    
    0 讨论(0)
  • 2020-11-27 21:46

    This ought to do for now...

    public class MultiValueDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
    {
        private Dictionary<TKey, LinkedList<TValue>> _dict = new Dictionary<TKey, LinkedList<TValue>>();
    
        public void Add(TKey key, TValue value)
        {
            if(!_dict.ContainsKey(key)) _dict[key] = new LinkedList<TValue>();
            _dict[key].AddLast(value);
        }
    
        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
        {
            foreach (var list in _dict)
                foreach (var value in list.Value)
                    yield return new KeyValuePair<TKey, TValue>(list.Key, value);
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
    
    0 讨论(0)
  • 2020-11-27 21:47

    It doesn't exist, but you can build one pretty quickly from Dictionary and List:

    class MultiDict<TKey, TValue>  // no (collection) base class
    {
       private Dictionary<TKey, List<TValue>> _data =  new Dictionary<TKey,List<TValue>>();
    
       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<TValue>() { v}) ;
       }
    
       // more members
    }
    
    0 讨论(0)
提交回复
热议问题