C# MultiMap

Generic

A MultiMap has multiple values at a key. With it we add multiple values to a single key in a Dictionary. We see an example implementation of the MultiMap associative array in the C# language. We then use the class.

Dictionary

Example

Class: shapes

The base class library does not provide a MultiMap. This type is a Dictionary with values of type List. Here we show a MultiMap façade class. It uses a string key and any type of value. We add objects at specific keys.

Note:You can find more on classes, and generic classes, on this website as well.

ClassGeneric Class
Program that implements MultiMap: C#

public class MultiMap<V>
{
    // 1
    Dictionary<string, List<V>> _dictionary =
	new Dictionary<string, List<V>>();

    // 2
    public void Add(string key, V value)
    {
	List<V> list;
	if (this._dictionary.TryGetValue(key, out list))
	{
	    // 2A.
	    list.Add(value);
	}
	else
	{
	    // 2B.
	    list = new List<V>();
	    list.Add(value);
	    this._dictionary[key] = list;
	}
    }

    // 3
    public IEnumerable<string> Keys
    {
	get
	{
	    return this._dictionary.Keys;
	}
    }

    // 4
    public List<V> this[string key]
    {
	get
	{
	    List<V> list;
	    if (!this._dictionary.TryGetValue(key, out list))
	    {
		list = new List<V>();
		this._dictionary[key] = list;
	    }
	    return list;
	}
    }
}
Squares

In part 1, it uses a Dictionary of string keys. This code always uses string keys, which are the most common. Its goal is to simplify. In part 2, it provides a simple Add method. This method is implemented with TryGetValue.

TryGetValueContainsKey

To continue, we add the value to the List in part 2A. The value is always stored at its key, even with duplicates. In part 3, it exposes Keys. You will want to enumerate over Keys in your code. In part 4, it provides an indexer.

Tip:This provides natural and short syntax for accessing the MultiMap. It returns an empty List if nothing exists.

ListIndexer

Note:The original implementation of MultiMap here did not add a new list to the Dictionary upon creation in the indexer.

However:This reduced the usefulness of the indexer. Artem Korneev wrote in with the improved implementation of get.

Example 2

Bool keyword

Next, this program uses the MultiMap. It demonstrates the Add method, and loops through all the Keys and then the values. The two "key1" strings indicate the same value location, so the second value is added to the first in the List.

Bool
Program that uses MultiMap with bools: C#

class Program
{
    static void Main()
    {
	bool b1 = true;
	bool b2 = false;
	bool b3 = false;

	MultiMap<bool> m1 = new MultiMap<bool>();
	m1.Add("key1", b1);
	m1.Add("key1", b2);
	m1.Add("key2", b3);

	foreach (string k in m1.Keys)
	{
	    foreach (bool b in m1[k])
	    {
		Console.WriteLine(k + "=" + b);
	    }
	}
	Console.ReadLine();
    }
}

Output

key1=True
key1=False
key2=False

Example 3

String type

To continue, this example shows how you could use MultiMap with strings to store names within categories. The strings "cat" and "dog" will both be stored under "animal". This is similar to the previous example.

Strings
Program that uses MultiMap with strings: C#

class Program
{
    static void Main()
    {
	const string s1 = "cat";
	const string s2 = "dog";

	MultiMap<string> m1 = new MultiMap<string>();
	m1.Add("animal", s1);
	m1.Add("animal", s2);
	m1.Add("human", "tom");
	m1.Add("human", "tim");
	m1.Add("mineral", "calcium");

	foreach (string k in m1.Keys)
	{
	    foreach (string v in m1[k])
	    {
		Console.WriteLine(k + "=" + v);
	    }
	}

	Console.ReadLine();
    }
}

Output

animal=cat
animal=dog
human=tom
human=tim
mineral=calcium

Summary

We saw an implementation of the MultiMap class in the C# language. My advice is to keep it simple. If you don't need a complex class, it is best to use the minimum that meets your needs.

Thus:The façade here simplifies Dictionary and wraps it with MultiMap features.


C#: Collections