34

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
oillio
  • 4,528
  • 4
  • 29
  • 36
  • Are you looking to specifically use an int for the key? If a string would suffice, the NameValueCollection may be of use - multiple values can be assigned to a key – Russ Cam Sep 03 '10 at 22:32

6 Answers6

53

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
  • 767,688
  • 176
  • 1,542
  • 1,434
  • 1
    From the docs: *There is no public constructor to create a new instance of a Lookup. Additionally, Lookup objects are immutable, that is, you cannot add or remove elements or keys from a Lookup object after it has been created.* – Douglas Sep 03 '10 at 22:28
  • @Douglas: Thanks for the comment. I have updated my answer to cover this point. – Mark Byers Sep 03 '10 at 22:57
14

I would recommend doing something like this:

var dict = new Dictionary<int, HashSet<string>>();
dict.Add(1, new HashSet<string>() { "first", "second" });
ChaosPandion
  • 75,687
  • 16
  • 116
  • 154
8

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
  • 26,707
  • 6
  • 66
  • 88
7

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
  • 650
  • 6
  • 8
1

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
  • 44,468
  • 23
  • 118
  • 147
0

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
  • 73,377
  • 7
  • 157
  • 198