37

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,748
  • 5
  • 31
  • 37
  • 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

55

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
  • 811,555
  • 193
  • 1,581
  • 1,452
  • 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
  • 77,506
  • 18
  • 119
  • 157
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
  • 27,626
  • 6
  • 70
  • 90
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
  • 660
  • 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
  • 45,296
  • 24
  • 122
  • 150
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
  • 77,689
  • 9
  • 166
  • 211