C# How do you loop through multiple dictionaries? - c#

A standard dictionary would look like this:
public Dictionary<int, DictionarySetup> H = new Dictionary<int, DictionarySetup>()
{
{18000, new DictionarySetup { Some values }},
};
Ranging from A-T, all of these are in a class called DictionaryInit, right now I check the value if there's a match with this boolean:
public Boolean Dictionary_Test(Dictionary<int, DictionarySetup> AccountLexicon)
{
DictionarySetup ClassValues;
if (AccountLexicon.TryGetValue(MapKey, out ClassValues))
{
return true;
}
return false;
}
Now, I'm looking for a more efficient method to loop through each Dictionary and, if there's a match, get that particular dictionary for use in a subsequent method, this is what it looks like now in an if/else:
if(Dictionary_Test(theDictionary.C) == true)
{
Dictionary_Find(Account_String, rowindex, theBSDictionary.C, Cash_Value, txtCurrency.Text);
}
else if (Dictionary_Test(theDictionary.D) == true)
{
Dictionary_Find(Account_String, rowindex, theDictionary.D, Cash_Value, txtCurrency.Text); //Method that makes use of the dictionary values, above dictionary checks only if it exists
}
With dictionaries from A-T, that would be alot of if/else's! Is there a better way to do this? I've found one thread mentioning this same topic, by adding the dictionaries to a dictionary array[] then looping over it, but how do I get the name of the matching dictionary if a match is found or make my second method, Dictionary_Find, use the matching dictionary?

Another possible solution, you could use reflection to get each dictionary from A-T from the DictionaryInit class. Create an array that contains values A-T, loop through the array and use reflection to get the dictionary, and test that dictionary, if you find a match, return that dictionary and exit the loop. Something like:
var dicts = new[]{"A", "B", ......., "T"}
foreach (var dict in dicts)
{
var found = CheckDictionary(theDictionary, dict);
if (found != null)
{
Dictionary_Find(Account_String, rowindex, (Dictionary<int, DictionarySetup>)found, Cash_Value, txtCurrency.Text);
break;
}
}
public static object CheckDictionary(object dictClass, string dictName)
{
var theDictionary = dictClass.GetType().GetProperty(dictName).GetValue(dictClass, null);
return Dictionary_Test(theDictionary) ? theDictionary : null;
}
I've just quickly grabbed some code from a project I've done and modified it to suit but haven't tested it. Might need a few tweaks but hopefully gets you close!

// put dictionary A ~ T to a list of dictionary
List<Dictionary<int, DictionarySetup>> dictionaries = new List<Dictionary<int, DictionarySetup>>{A,B,C, ... , T}; // Replace ... with D,E,F, etc. until T
// iterate each dictionary and if found, exit the loop
foreach(var dict in dictionaries)
{
if(Dictionary_Test(dict))
{
Dictionary_Find(Account_String, rowindex, dict, Cash_Value, txtCurrency.Text);
break;
}
}

Related

Why does comparing each of C# Dictionary Key/Value pair gives different result, than comparing Dictionary Keys and Values done at once?

I've currently had to put some data in dictionary, to check whether some of the actual data, match the expected one for some of my tests.
For the task I've created a Dictionary that looked somehow like that:
Dictionary<string, string> dict = new Dictionary<string, string>(){
{a, a},
{b, b},
{c, c}
};
The first that I've tried was to compare the Dictionary Values and Keys in conditional statement like shown below and I was kinda suprised with the false result of this conditional statement:
if(dict.Keys.Equals(dict.Values)) {
///// received false as a result here //////
}
When I then tried the next approach which was to iterate through all of dictionary items and to compare each of their Value Key pairs, it suddenly resulted in giving me the expected (true) result for all items of Dictionary:
foreach (var item in dict) {
if (item.Key.Equals(item.Value))
{
///// received true as a result /////
}
else { other code here }
}
Why did I get the false result for the first approach described?
You expect them both to be an ICollection if you look into the docs.
Have a look in the reference source of the dictionary class.
The Keys and Values Properties are implemented using different collection-types.
// Line 135
public KeyCollection Keys {
get {
Contract.Ensures(Contract.Result<KeyCollection>() != null);
if (keys == null) keys = new KeyCollection(this);
return keys;
}
}
// Line 157
public ValueCollection Values {
get {
Contract.Ensures(Contract.Result<ValueCollection>() != null);
if (values == null) values = new ValueCollection(this);
return values;
}
}
Also if you look into the KeyCollection and ValueCollection Classes, you will notice, that there is no other implementation of the Equals() Method. As those classes don't derive from any other class, you may be sure that dict.Keys.Equals(dict.Values) will call the object.Equals() Method.
This call will obviously return false.

C# Populate dynamically nested Dictionary with unknown depth

I get an array of Nodes and a Value into my Method which have to be nested into a Dictionary Structure. But I really need help with the logic here.
I did a static Test which shows what I need:
public static Dictionary<string, object> CreateNestedDictionary(string[] chainNodes, string value)
{
// Testvalues:
// ["application", "deepNode", "evenDeeperNode"], "Value"
var container = new Dictionary<string, object>();
container.Add("application", new Dictionary<string, object>() { { "deepNode", new Dictionary<string, string>(){{"evenDeeperNode", "Value" } }}});
return container;
}
So basically, I have a Dictionary<string, object> variable, which can contain an infinite number of Dictionaries of the same type. At the very end, I need a Dictionary<string, string> to define the last node and the value.
By Node I mean the Key of the Dictionary. Those will later be represented in a JSON Sctructure.
The thing is, that I don't know how many Elements I get in chainNodes. Also, I may have to call this Method several times and add more Nodes. I would then have several chainNodes which have to go into the same Dictionary structure. Iwould then have to make sure that the Keys stay unique.
Is there any easy way to populate this structure dynamically? Or even a LINQ approach that deals with this?
Any advice is much appreciated. Thank you in advance
Update
After the comments I realized I did a really bad job explaining this.
Here is another example:
public static Dictionary<string, object> CreateNestedDictionary(string[] chainNodes, string value)
{
// Testvalues:
// ["application", "deepNode", "evenDeeperNode"], "Value"
var container = new Dictionary<string, object>();
for (int i = 0; i < chainNodes.Length; i++)
{
if (i != chainNodes.Length -1)
{
container.Add(chainNodes[i], new Dictionary<string, object>()); // fill this empty Dictionary
}
else
{
container.Add(chainNodes[i], value);
}
}
}
Adding the last Dictionary is easy but I don't know how to fill the Dictionaries after the first.
If I have understood this correctly: chainNodes is a list of the names, and value goes in the deepest dictionary (with name chainNodes[chainNodes.Length-1]).
Summary: you need to iterate and special case the deepest node.
Something recursive is probably easiest, starting with the pure creation case (no need to check for existing entries).
public Dictionary<string, object> CreateNestedDictionary(string[] chainNodes, object value) {
return DoCreate(chainNodes, value, 0);
}
private Dictionary<string, object> DoCreate(string[] chainNodes, object value, int index) {
var res = new Dictionary<string, object>();
if (index == chainNodes.Length - 1) {
// Bottom out the recursion
res.Add(chainNodes[index], value);
} else {
res.Add(chainNodes[index], DoCreate(chainNodes, value, index+1));
}
return res;
}
Recursion naturally allows you to special case that last string because that is the end case that recursion must have.
For the adding to an existing collection case, you need to change the recursion to:
Pass down the current node
Check if chainNodes[index] key exists and use that entry or create a new one.
Here's how I implemented infinite nesting Dictionaries.
My structure is: Dict([bool],object), ending with [bool] = true.
public void Init(bool[] boolArray)
{
BoolDict = new Dictionary<bool, object>();
Dictionary<bool, object> parent = BoolDict;
for (int index = 0; index < boolArray.Length; index++)
{
if (index < boolArray.Length - 1)
{
Dictionary<bool, object> nestedDict = new Dictionary<bool, object>();
parent.Add(boolArray[index], nestedDict);
parent = nestedDict;
}
else
{
parent.Add(boolArray[index], true);
}
}
}
It's important to save the new Dict as the parent so that you can add to the new parent which you created in the previous iteration.
You could remove the first value from the chainNodes and recursively call the method if there are any more values until you reach the end.
I'm with #Blorgbeard, though in that, this is a poor structure.
public static Dictionary<string, object> CreateNestedDictionary(string[] chainNodes, string value)
{
// Testvalues:
// ["application", "deepNode", "evenDeeperNode"], "Value"
var key = chainNodes.First();
chainNodes = chainNodes.Skip(1).ToArray();
return new Dictionary<string, object> { { key, chainNodes.Any() ? CreateNestedDictionary(chainNodes, value) : value } };
}

I need to create a dictionary where each key can map to several values

Im trying to figure out how I can create something similar to a dictionary, but where each key can map to several values.
Basically what I need is to be able to assign multiple values to the same key without knowing in advance how many values each key will correspond to. I also need to be able to add values to an existing key on multiple occasions. It would also be nice if I could detect when a key + value combination already exists.
An example of how the program should work:
list.Add(1,5);
list.Add(3,6);
list.Add(1,7);
list.Add(5,4);
list.Add(1,2);
list.Add(1,5);
This should ideally produce a table like this:
1: 5, 7, 2
3: 6
5: 4
Is there any existing construction in C# that I can use for this or do I have to implement my own class? Implementing the class would probably not be a big problem, but Im a bit short on time so it would be nice if I could use something that already exists.
Quick Solution
As you have already mentioned, a Dictionary would be the best type to use. You can specify both the key type and value type to meet your needs, in your case you want an int key and a List<int> value.
This is easy enough to create:
Dictionary<int, List<int>> dictionary = new Dictionary<int, List<int>>();
The challenge then comes with how you add records, you cannot simply do Add(key, value) because that will cause conflict which duplicate keys. So you have to first retrieve the list (if it exists) and add to that:
List<int> list = null;
if (dictionary.ContainsKey(key))
{
list = dictionary[key];
}
else
{
list = new List<int>();
dictionary.Add(key, list);
}
list.Add(newValue);
Preferred Solution
This is obviously a few too many lines to use each time you want to add an item, so you would want to throw that into a helper function, or my preference would be to create your own class that extends the functionality of Dictionary. Something like this:
class ListDictionary<T1, T2> : Dictionary<T1, List<T2>>
{
public void Add(T1 key, T2 value)
{
if (this.ContainsKey(key))
{
this[key].Add(value);
}
else
{
List<T2> list = new List<T2>() { value };
this.Add(key, list);
}
}
public List<T2> GetValues(T1 key)
{
if(this.ContainsKey(key))
return this[key];
return null;
}
}
Which you can then use as easy as you originally wanted:
ListDictionary<int, int> myDictionary = new ListDictionary<int, int>();
myDictionary.Add(1,5);
myDictionary.Add(3,6);
//...and so on
Then to get the list of values for your desired key:
List<int> keyValues = myDictionary.GetValues(key);
//check if NULL before using, NULL means the key does not exist
//alternatively you can check if the key exists with if (myDictionary.ContainsKey(key))
You can create a dictionary of Lists quite easily e.g.
Dictionary<int, List<int>> dictionary = new Dictionary<int, List<int>>()
An Alternative if you have created a list of items and want to separate them into groups with different keys, which serves much the same purpose is the Lookup class.
Dictionary<int, List<int>> dictionary = new Dictionary<int, List<int>>();
public void AddIfNotExistInDic(int key, int Value) {
List<int> list = null;
if (dictionary.ContainsKey(key)) {
list = dictionary[key];
}
else {
list = new List<int>();
dictionary.Add(key, list);
}
if (!list.Contains(Value)) {
list.Add(Value);
}
}
You can use Dictionary<TKey, TValue>, the TKey would be int and TValue would be List<int>, You can add as many element in List as it grow autmatically.
Dictionary <int, List<int>> dic = new Dictionary<int, List<int>>();
The way you can access the value would change, you can for instance add element in dictionary like
void AddToYourCustomDictionary(int key, int someValue)
{
if(!dic.ContainsKey(key))
{
dic.Add(key, new List<int>());
dic[key].Add(someValue);
}
else
dic[key].Add(someValue); //Adding element in existing key Value pair
}
To access element in Dictionary Key -> value i.e list,
Console.WriteLine(dic[key][indexOfList]);

How to assign key=>value pairs in a Dictionary?

Here is my code:
string[] inputs = new[] {"1:2","5:90","7:12","1:70","29:60"};
//Declare Dictionary
var results = new Dictionary<int, int>();
//Dictionary<int, int> results = new Dictionary<int, int>();
foreach(string pair in inputs)
{
string[] split = pair.Split(':');
int key = int.Parse(split[0]);
int value = int.Parse(split[1]);
//Check for duplicate of the current ID being checked
if (results.ContainsKey(key))
{
//If the current ID being checked is already in the Dictionary the Qty will be added
//Dictionary gets Key=key and the Value=value; A new Key and Value is inserted inside the Dictionary
results[key] = results[key] + value;
}
else
{
//if No duplicate is found just add the ID and Qty inside the Dictionary
results[key] = value;
//results.Add(key,value);
}
}
var outputs = new List<string>();
foreach(var kvp in results)
{
outputs.Add(string.Format("{0}:{1}", kvp.Key, kvp.Value));
}
// Turn this back into an array
string[] final = outputs.ToArray();
foreach(string s in final)
{
Console.WriteLine(s);
}
Console.ReadKey();
I want to know if the difference if there is between assigning a key=>value pair in a dictionary.
Method1:
results[key] = value;
Method2:
results.Add(key,value);
In method 1, the function Add() was not called but instead the Dictionary named 'results' assigns somehow sets a Key-Value pair by stating code in method1, I assume that it somehow adds the key and value inside the dictionary automatically without Add() being called.
I'm asking this because I'm currently a student and I'm studying C# right now.
Sir/Ma'am, your answers would be of great help and be very much appreciated. Thank you++
The Dictionary<TKey, TValue> indexer's set method (the one that is called when you do results[key] = value;) looks like:
set
{
this.Insert(key, value, false);
}
The Add method looks like:
public void Add(TKey key, TValue value)
{
this.Insert(key, value, true);
}
The only difference being if the third parameter is true, it'll throw an exception if the key already exists.
Side note: A decompiler is the .NET developers second best friend (the first of course being the debugger). This answer came from opening mscorlib in ILSpy.
If the key exists in 1) the value is overwritten. But in 2) it would throw an exception as keys need to be unique

how to change Dictionary's value when enumerate it?

how to change Dictionary's value when enumerate it?
the following code doesn't work, because we can not change dictionary's value when enumerating it. Is there any way to get around it? Or NO WAY? Thanks
foreach (KeyValuePair<string, int> kvp in mydictionary)
{
if (otherdictionary.ContainsKey(kvp.Key))
{
mydictionary[kvp.Key] = otherdictionary[kvp.Key];
}
else
{
otherdictionary[kvp.Key] = mydictionary[kvp.Key];
}
}
The simplest way would be to take a copy first. As you only want the key value pairs, you might as well put them in a list rather than building a new dictionary though. Also, you can avoid doing quite as many lookups using TryGetValue.
var copy = myDictionary.ToList();
foreach (KeyValuePair<string, int> kvp in copy)
{
int otherValue;
if (otherdictionary.TryGetValue(kvp.Key, out otherValue))
{
mydictionary[kvp.Key] = otherValue;
}
else
{
otherdictionary[kvp.Key] = kvp.Value;
}
}
Make a copy of the values you need to enumerate over before you enumerate over them, then you can change the original source.
Since you don't actually use the value, you can change the code to this:
foreach (string key in mydictionary.Keys.ToArray())
if (otherdictionary.ContainsKey(key))
mydictionary[key] = otherdictionary[key];
else
otherdictionary[key] = mydictionary[key];
Note the use of .ToArray() there to make a temporary array copy of the key collection. This is now separate from the source dictionary, so you can change the dictionary all you want.
another option, copy the keys collection to an array and use it in for each loop -
string[] arr1 = new string[mydictionary.Count];
mydictionary.Keys.CopyTo(arr1,0);
foreach (string j in arr1)
{
if (otherdictionary.ContainsKey(j))
{
mydictionary[j] = otherdictionary[j];
}
else
{
otherdictionary[j] = mydictionary[j];
}
}

Categories

Resources