C# Dictionary - One Key, Many Values

One Key to multiple values dictionary in C#?

A dictionary is a key-value pair, where the value is fetched depending on the key. The keys are all unique.

Now if you want a Dictionary with 1 keytype and multiple value types, you have a few options:

first is to use a Tuple

var dict = new Dictionary<KeyType, Tuple<string, string, bool, int>>()

The other is to use (with C# 4.0 and above):

var dict = new Dictionary<KeyType, dynamic>()

the System.Dynamic.ExpandoObject can have value of any type.

using System;
using System.Linq;
using System.Collections.Generic;

public class Test {
public static void Main(string[] args) {
dynamic d1 = new System.Dynamic.ExpandoObject();
var dict = new Dictionary<int, dynamic>();
dict[1] = d1;
dict[1].FooBar = "Aniket";
Console.WriteLine(dict[1].FooBar);
dict[1].FooBar = new {s1="Hello", s2="World", s3=10};
Console.WriteLine(dict[1].FooBar.s1);
Console.WriteLine(dict[1].FooBar.s3);
}
}

c# dictionary How to add multiple values for single key?

Update: check for existence using TryGetValue to do only one lookup in the case where you have the list:

List<int> list;

if (!dictionary.TryGetValue("foo", out list))
{
list = new List<int>();
dictionary.Add("foo", list);
}

list.Add(2);



Original:
Check for existence and add once, then key into the dictionary to get the list and add to the list as normal:

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

if (!dictionary.ContainsKey("foo"))
dictionary.Add("foo", new List<int>());

dictionary["foo"].Add(42);
dictionary["foo"].AddRange(oneHundredInts);

Or List<string> as in your case.

As an aside, if you know how many items you are going to add to a dynamic collection such as List<T>, favour the constructor that takes the initial list capacity: new List<int>(100);.

This will grab the memory required to satisfy the specified capacity upfront, instead of grabbing small chunks every time it starts to fill up. You can do the same with dictionaries if you know you have 100 keys.

Dictionary one key many values in code c#

Make a dictionary with List<string> as value, and then just add values :

foreach(var d in c)
{
if (!dict.ContainsKey(d.Key))
dict.Add(d.Key, new List<string>());
dict[d.Key].Add(d.Value);
}

and later you can get comma delimited string from list with string.Join

string commaDelimitedList = string.Join(",", valueList.ToArray());

Dictionary with multiple values for each key?

Simple: Use Dictionary<string,List<Order>>

C# Dictionary: Multiple KEYS per Value

Do the dictionary the other way around and make the value a list of items.

if for example Value is a string and Key 1-4 are ints your dictionary could look something like:

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

retrieving Value by theDictionary["Value"] would then return a list of ints containing 1, 2, 3 and 4.

Edit - Added example:

var theDictionary = new Dictionary<string, List<string>>
{
{"Value", new List<string> {"Key 1", "Key 2", "Key 3", "Key 4", "Key 5",}},
{"Value2", new List<string> {"Key 5", "Key 2"}}
};

var oneToFour = theDictionary["Value"];

Create a Dictionary with multiple keys and get value using one of keys

Dictionaries in .NET are expected to have close to O(1) lookup times. To achieve this, they make use of the GetHashCode() and Equals() methods of the key objects. The resulting hash code is used to divide the dictionary's contents into partitions. When you look up an item, the partition is identified using the hash code, all the items in that partition with a matching hash code* are compared to the key you're looking up using the Equals() method.

Here you are trying to create a dictionary with two keys for every object. You're doing this using a Tuple to make one key. The GetHashCode() result of a Tuple is based on both of its values, so the performance of a dictionary is lost if you want to look up values by only half of the key. You would need to go through the entire dictionary comparing each individual item, rendering it little better than a list.

One solution would be to make a dictionary that has a string->int key lookup, and then the other dictionary just be int->string. This would require two lookups when using string keys, but might be a good solution.

Example:

Dictionary<string, int> stringKeyToIntKey = new Dictionary<string, int>();
Dictionary<int, string> intKeyDict = new Dictionary<int, string>();

intKeyDict[1] = "Test";
stringKeyToIntKey["I1"] = 1;

Console.WriteLine(intKeyDict[1]);
Console.WriteLine(intKeyDict[stringKeyToIntKey["I1"]]);

An add method could look like this:

public void AddEntry(int intKey, string stringKey, string value)
{
intKeyDict[intKey] = value;
stringKeyToIntKey[stringKey] = intKey;
}

And you could wrap TryGetValue to make life easier:

public bool TryGetValue(string stringKey, out string value)
{
value = null;
return stringKeyToIntKey.TryGetValue(stringKey, out int intKey) && intKeyDict.TryGetValue(intKey, out value);
}

Delete would look like this:

public void DeleteEntry(string stringKey)
{
if (stringKeyToIntKey.TryGetValue(stringKey, out int intKey))
{
intKeyDict.Remove(intKey);
stringKeyToIntKey.Remove(stringKey);
}
}

You would have to make sure that items are added and removed from both dictionaries at the same time. When you add an item to intKey, you would need to add the corresponding key mapping to stringKeyToIntKey.

Alternatively, you could have two dictionaries: one with a string key and one with an int key, and each would have the same values. Again you would have to add and remove items at the same time, and you would also have to update the values in both at the same time.

Example:

Dictionary<string, string> stringKeyDict = new Dictionary<string, string>();
Dictionary<int, string> intKeyDict = new Dictionary<int, string>();

stringKeyDict["I1"] = "hello";
intKeyDict[1] = "hello";

Console.WriteLine(stringKeyDict["I1"]);
Console.WriteLine(intKeyDict[1]);

This is my favoured approach where the values are class instances, since both dictionaries will reference the same class instances for my items, and thus changes to properties of those instances will be reflected in both. For strings, however, the first option might be better.

* Hash codes are not unique and multiple objects can potentially have the same hash code, even if their values are not the same



Related Topics



Leave a reply



Submit