using System.Collections;
using System.Collections.Generic;
public static void Main()
var tests = new MultiMapTests();
tests.WhenKeyExist_CanAddMultipleValues();
tests.WhenUnion_ShouldHaveBothKeysAndValues();
Console.WriteLine("It seems success");
public class MultiMapTests{
public void WhenKeyExist_CanAddMultipleValues(){
var mp = new MultiMap<int, string>();
Assert.That(mp.ContainsKey(1), Is.True);
Assert.That(mp[1].Contains("Test2"), Is.True);
Assert.That(mp[1].Contains("Test"), Is.True);
public void WhenUnion_ShouldHaveBothKeysAndValues(){
var mp = new MultiMap<int, string>(){
var mp2 = new MultiMap<int, string>(){
Assert.That(mp3.ContainsKey(1), Is.True);
Assert.That(mp3.ContainsKey(2), Is.True);
Assert.That(mp3.ContainsKey(3), Is.True);
Assert.That(mp3[3].Contains("a"), Is.True);
public class MultiMap<TKey, TValue> : IEnumerable<KeyValuePair<TKey, HashSet<TValue>>> where TKey : struct{
private readonly Dictionary<TKey, HashSet<TValue>> _dic = new Dictionary<TKey, HashSet<TValue>>();
public HashSet<TValue> this[TKey key]{
if(_dic.ContainsKey(key)){
return new HashSet<TValue>();
public void Add(TKey key, TValue val){
if(!_dic.ContainsKey(key)){
_dic.Add(key, new HashSet<TValue>());
public void Add(TKey key, HashSet<TValue> val){
if(!_dic.ContainsKey(key)){
_dic[key].UnionWith(val);
public bool Remove(TKey key, TValue val){
if(_dic.TryGetValue(key, out var hashSet)){
return hashSet.Remove(val);
IEnumerator IEnumerable.GetEnumerator(){
return this.GetEnumerator();
public bool ContainsKey(TKey key){
return _dic.ContainsKey(key);
public IEnumerator<KeyValuePair<TKey, HashSet<TValue>>> GetEnumerator(){
foreach(var kvp in _dic){
public static class MultiMapExtensions{
public static MultiMap<TKey, TValue> Union<TKey, TValue>(this MultiMap<TKey, TValue> first, MultiMap<TKey, TValue> second)
var result = new MultiMap<TKey, TValue>();
foreach (var kvp in first)
result.Add(kvp.Key, kvp.Value);
foreach (var kvp in second)
result.Add(kvp.Key, kvp.Value);
public static MultiMap<TKey, TValue> Except<TKey, TValue>(this MultiMap<TKey, TValue> first, MultiMap<TKey, TValue> second)
var result = new MultiMap<TKey, TValue>();
foreach(var kvp in first){
if(!second.ContainsKey(kvp.Key)){
result.Add(kvp.Key, kvp.Value);