tags:

views:

121

answers:

6

I need a Dictionary like object that can store multiple entries with the same key. Is this avaliable as a standard collection, or do I need to roll my own?

To clarify, I want to be able to do something like this:

var dict = new Dictionary<int, String>();
dict.Add(1, "first");
dict.Add(1, "second");

foreach(string x in dict[1])
{
    Console.WriteLine(x);
}

Output:

first
second
+4  A: 

I would recommend doing something like this:

var dict = new Dictionary<int, HashSet<string>>();
dict.Add(1, new HashSet<string>() { "first", "second" });
ChaosPandion
+6  A: 

In .NET 3.5 you can use a Lookup instead of a Dictionary.

var items = new List<KeyValuePair<int, String>>();
items.Add(new KeyValuePair<int, String>(1, "first"));
items.Add(new KeyValuePair<int, String>(1, "second"));
var lookup = items.ToLookup(kvp => kvp.Key, kvp => kvp.Value);

foreach (string x in lookup[1])
{
    Console.WriteLine(x);
}

The Lookup class is immutable. If you want a mutable version you can use EditableLookup from MiscUtil.

Mark Byers
From the docs: *There is no public constructor to create a new instance of a Lookup<TKey, TElement>. Additionally, Lookup<TKey, TElement> objects are immutable, that is, you cannot add or remove elements or keys from a Lookup<TKey, TElement> object after it has been created.*
Douglas
@Douglas: Thanks for the comment. I have updated my answer to cover this point.
Mark Byers
+2  A: 

Dictionary<T,K> does not support such behavior and there's no collection in the base class library providing such behavior. The easiest way is to construct a composite data structure like this:

var data = new Dictionary<int, List<string>>();

As the second parameter you should use a collection which provides the qualities you are looking for, i.e. stable order ⇒ List<T>, fast access HashSet<T>, etc.

Ondrej Tucny
+1  A: 

What you're looking for isn't actually a Dictionary in the traditional sense (see Associative Array).

There's no class, as far as I'm aware, that offers this in the framework (System.Linq.Lookup doesn't expose a constructor), but you could create a class yourself that implements ILookup<TKey, TElement>

Rob
A: 

You could perhaps use a Dictionary on your primary key, in which each element is a List or other collection on your secondary key. To add an item to your data structure, see if the primary key exists. If not, create a new single-item list with your Value and store it in the dictionary. If the primary key does exist, add your Value to the list that's in the dictionary.

supercat
A: 

You definitely want to use NameValueCollection:

using System.Collections.Specialized;

NameValueCollection nvc = new NameValueCollection();
nvc.Add("pets", "Dog");
nvc.Add("pets", "Rabbit");
Console.WriteLine(nvc["pets"]);
//returns Dog,Rabbit
Amit
NVC only works with strings.
oillio