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 } };
}
Related
I am trying to get my method to return a matchKey's value as I pass this to the method but the value is returning as Null. Also it shows my dictionary contains the Key and the value i am looking for also my if(Items.TryGetValue(item.Key.Contains(matchKey).ToString() returns true but it does not add it to the second dictionary I have.. My Items dictionary has all the key and values and I am able to return that.. but I am trying to extract one of the key which is "id" and its value "80" from that and adding to my second dictionary keyValues and returning that if it contains..
Here is the Json after Serializing
{"UserId":"","UserId2":"","id":"80"}
public Dictionary<string, string> GetKeyAndValues(string matchKey)
{
string data = JsonConvert.SerializeObject(dataEntries);
Dictionary<string, string> Items = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
Dictionary<string, string> keyValues = new Dictionary<string, string>();
foreach (KeyValuePair<string, string> item in Items)
{
if (!Items.ContainsKey(item.Key))
{
Items.Add(item.Key.ToString(), item.Value.ToString());
}
var value = Items[matchKey];
if(Items.TryGetValue(item.Key.Contains(matchKey).ToString(), out value))
{
keyValues.Add(matchKey, value);
return keyValues;
}
}
return Items;
}
The major problem in your code is in this line of code:
if (Items.TryGetValue(item.Key.Contains(matchKey).ToString(), out value))
It doesn't check if an item with the key matchKey is contained in the Items dictionary. This sub-expression item.Key.Contains(matchKey) checks if matchKey is contained in the Items and returns true or false. Therefore this problem line checks if a key with value true of false is contained in the Items.
Here is a fixed method GetKeyAndValues:
public static Dictionary<string, string> GetKeyAndValues(string matchKey)
{
string data = JsonConvert.SerializeObject(dataEntries);
Dictionary<string, string> Items = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
// We don't need a loop to check if a key "matchKey" is contained in the "Items".
// Items.TryGetValue(matchKey, out string value) checks if "matchKey" is contained
// in the "Items", and if it is contained it returns an appropriate "value".
if (Items.TryGetValue(matchKey, out string value))
{
// Here we create a Dictionary with a single pair (matchKey, value).
return new Dictionary<string, string> {{matchKey, value}};
}
return Items;
}
Here is a useful link to the documentation of the method Dictionary.TryGetValue.
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;
}
}
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]);
I understand why there isn't a method built in to do this, however I want a collection object that will allow Value change possibly during Enumeration.
Imagine the following:
Dictionary<string, List<string>> test = new Dictionary<string, List<string>> {{"key", null}};
Lets say I have 20 of these within a class which implements IEnumberable
I'd like to use lambda or a simple foreach to iterate through the class and find the object matching a key, then store my List<T> with the Value parameter.
You might be looking for a collection called multimap. See here for my implementation of it.
As you have discovered you can't change a DictionaryEntry through the Value property - you have to go through the Item accessor using the Key.
One option is to turn your Where results to an array then loop to get the matching Keys:
Dictionary<string, List<string>> test = new Dictionary<string, List<string>>
{{"key", null}};
test.Add("newKey",null);
var matches = test.Where(di => di.Key == "key").ToArray();
foreach(var di in matches) {
test[di.Key] = new List<string> {"one","two"};
You can just use this to modify a value in a dictionary:
public static void ChangeValue(string indexKey,List<string> newValue)
{
if (test.ContainsKey(indexKey))
keysDictionary[indexKey] = newValue;
}
You could avoid using an enumerator altogether, e.g.
var data = myEnumerable.ToArray();
for(var i = 0; i < data.Length; i++) {
// here you can manipulate data[i] to your heart's content
}
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