Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a Dictionary<string, object> collection which allows multiple keys?

Tags:

c#

collections

I currently have a menu with subitems that is being stored in this dictionary variable:

private Dictionary<string, UserControl> _leftSubMenuItems 
    = new Dictionary<string, UserControl>();

So I add views to the e.g. the "Customer" section like this:

_leftSubMenuItems.Add("customers", container.Resolve<EditCustomer>());
_leftSubMenuItems.Add("customers", container.Resolve<CustomerReports>());

But since I am using a Dictionary, I can only have one key named "customers".

My natural tendency would be to now create a custom struct with properties "Section" and "View", but is there a .NET collection is better suited for this task, something like a "MultiKeyDictionary"?

ANSWER:

Thanks maciejkow, I expanded your suggestion to get exactly what I needed:

using System;
using System.Collections.Generic;

namespace TestMultiValueDictionary
{
    class Program
    {
        static void Main(string[] args)
        {
            MultiValueDictionary<string, object> leftSubMenuItems = new MultiValueDictionary<string, object>();

            leftSubMenuItems.Add("customers", "customers-view1");
            leftSubMenuItems.Add("customers", "customers-view2");
            leftSubMenuItems.Add("customers", "customers-view3");
            leftSubMenuItems.Add("employees", "employees-view1");
            leftSubMenuItems.Add("employees", "employees-view2");

            foreach (var leftSubMenuItem in leftSubMenuItems.GetValues("customers"))
            {
                Console.WriteLine(leftSubMenuItem);
            }

            Console.WriteLine("---");

            foreach (var leftSubMenuItem in leftSubMenuItems.GetAllValues())
            {
                Console.WriteLine(leftSubMenuItem);
            }

            Console.ReadLine();
        }
    }

    public class MultiValueDictionary<TKey, TValue> : Dictionary<TKey, List<TValue>>
    {

        public void Add(TKey key, TValue value)
        {
            if (!ContainsKey(key))
                Add(key, new List<TValue>());
            this[key].Add(value);
        }

        public List<TValue> GetValues(TKey key)
        {
            return this[key];
        }

        public List<TValue> GetAllValues()
        {
            List<TValue> list = new List<TValue>();

            foreach (TKey key in this.Keys)
            {
                List<TValue> values = this.GetValues(key);
                list.AddRange(values);
            }

            return list;
        }
    }

}

Answer 2:

Thanks Blixt for the tip about yield, here is GetAllValues with that change:

public IEnumerable<TValue> GetAllValues()
{
    foreach (TKey key in this.Keys)
    {
        List<TValue> values = this.GetValuesForKey(key);
        foreach (var value in values)
        {
            yield return value;
        }
    }
}

Answer 2 refactored further:

Here is a much more succinct way to do the same thing, thanks Keith:

public IEnumerable<TValue> GetAllValues()
{
    foreach (var keyValPair in this)
        foreach (var val in keyValPair.Value)
            yield return val;
}
like image 633
Edward Tanguay Avatar asked Jul 27 '09 09:07

Edward Tanguay


2 Answers

If you need variable number of values for one key, why not create Dictionary<string, List<UserControl>> ? Furthermore, you could inherit this class and create your own Add, get same syntax you're using now. This way you can avoid manual adding of empty lists before adding new control.

sth like this:

class MultiValueDictionary<TKey, TValue> : Dictionary<TKey, List<TValue>>
{

   public void Add(TKey key, TValue value)
   {
      if(!ContainsKey(key))
         Add(key, new List<TValue>());
      this[key].Add(value);
   }
}
like image 62
maciejkow Avatar answered Oct 04 '22 21:10

maciejkow


Check out NGenerics' HashList. It's a Dictionary which maintains a list of values for each key. Wintellect's PowerCollections library also has a handy MultiDictionary class which does things like automatically clean up when you remove the last value associated with a given key.

like image 28
Matt Howells Avatar answered Oct 04 '22 20:10

Matt Howells