I have 4 dictionary, each contain a button's name and the button's value.
I Have a List that contain the name of each dictionary
private Dictionary<string, int> TableArray = new Dictionary<string, int>() { { "ButtonRMT35", 35 }, { "ButtonRMT17", 17 }, { "ButtonRMT11", 11 }, { "ButtonRMT8", 8 }, { "ButtonRMT5", 5 } };
private Dictionary<string, int> ParArray = new Dictionary<string, int>() { { "ButtonRMP20", 20 }, { "ButtonRMP15", 15 }, { "ButtonRMP10", 10 }, { "ButtonRMP5", 5 } };
private Dictionary<string, int> MaxChipsRPArray = new Dictionary<string, int>() { { "ButtonRPC20", 20 }, { "ButtonRPC15", 15 }, { "ButtonRPC10", 10 }, { "ButtonRPC5", 5 } };
private Dictionary<string, int> QuestionSerieRPArray = new Dictionary<string, int>() { { "ButtonRPQ20", 20 }, { "ButtonRPQ15", 15 }, { "ButtonRPQ10", 10 }, { "ButtonRPQ5", 5 } };
public List<string> DictionaryList = new List<string>() { "TableArray", "ParArray", "MaxChipsRPArray", "QuestionSerieRPArray" };
I would like to do something like that
foreach (var dictionnary in DictionaryList)
{
foreach (var buttonName in dictionnary.Keys)
{
DoSomething();
}
}
Is there a way to do that?
The List<string> (DictionaryList) contains strings. Those strings are not variable identifiers (variable identifiers are not the same as C#/.NET strings; variable identifiers are lexical tokens in the C# language, being parsed by the C# compiler during the build of your program), and thus cannot be used to refer to some variable.[1]
Rather than maintaining strings in your DictionaryList, let it maintain the dictionaries itself:
private Dictionary<string, int> TableArray = ...
private Dictionary<string, int> ParArray = ...
private Dictionary<string, int> MaxChipsRPArray = ...
private Dictionary<string, int> QuestionSerieRPArray = ...
public List<Dictionary<string, int>> DictionaryList = new List<Dictionary<string, int>>()
{
TableArray, ParArray, MaxChipsRPArray, QuestionSerieRPArray
};
If you need to access the dictionaries by some name provided as a string (regardless whether that name would correlate with the variable/field names) you can turn the list into a dictionary of dictionaries (mapping some name to each of your dictionaries) instead:
private Dictionary<string, int> TableArray = ...
private Dictionary<string, int> ParArray = ...
private Dictionary<string, int> MaxChipsRPArray = ...
private Dictionary<string, int> QuestionSerieRPArray = ...
public Dictionary<string, <Dictionary<string, int>>> Dictionaries =
new Dictionary<string, <Dictionary<string, int>>>()
{
["TableArray"] = TableArray,
["MaxChipsRPArray"] = MaxChipsRPArray,
["QuestionSerieRPArray"] = QuestionSerieRPArray
};
...
foreach (var dictionary in Dictionaries.Values)
{
foreach (var buttonName in dictionary.Keys)
{
DoSomething();
}
}
You could then access an individual dictionary by name through the public Dictionaries field like this, for example:
var someDictionaryIWant = Dictionaries["MaxChipsRPArray"];
foreach (var buttonName in someDictionaryIWant.Keys)
{
DoSomething();
}
[1] I just told a grey lie here. For fields and properties, it would be possible to access fields/properties by their field/property name given as a string through a mechanism called "reflection". But reflection is cumbersome (likely even complicated for inexperienced programmers), slow, does not play well with trimming or compiling into native code, is normally not applicable to local variables declared inside methods, etc... But i think it's doubtful that you are looking for some dirty hack-ish way to solve your problem when there are cleaner and more straightforward solutions to your problem.
You are on a right track, however it would be hard to achieve by using variable names.
Use nested list, like this: List<Dictionary<string, int>> dictionaryList
Then add your dictionaries to the list, and iterate over them in the for each loop like you initially wanted to.
Related
I got stuck to change the following array to a dictionary.
public static string[][,] patterns = new string[][,]
{
new string[,] {
{ "1,2,3" },
{ "3,2,5" },
},
new string[,] {
{ "4,4,3" },
{ "7,1,2" },
},
};
This is what I have:
public Dictionary<string, string[]> patterns = new Dictionary<string, string[]>();
I can't fill the array with predefined values.
I want to change to a dictionary, because it has a key.
Can I also change the above array to a key and values format?
I want something like this: { "keyNameExample1", "1,2,3", "4,5,6", "etc"}. I want do something like this: patterns["keyNameExample", 1 (integer array pack)]; or patterns["keyNameExample", 2]; (to get the second arrays)
{ "keyNameExample1", "1,2,3", "4,5,6", "etc"} { "keyNameExample2", "5,7,8", "1,1,1", "etc"} and get it like this: patterns["keyNameExample1", 2]; or patterns["keyNameExample2", 1];
can make it even shorter like:
public static Dictionary<string, string[]> demo = new Dictionary<string, string[]>
{
{ "abc", new[]{"1","2"}},
{ "def", new[]{"3","4"}},
};
and with C# 9 you can even do:
public static Dictionary<string, string[]> demo = new()
{
{ "abc", new[]{"1","2"}},
{ "def", new[]{"3","4"}},
};
You can just make it a dictionary with a list, and I guess that covers your requirements (index access, variable number of integers for the index element). Here is an example (for the value list I am not sure, whether you really want a string or ints, in case just change the type):
// define dictionary
IDictionary<string, IList<int>> dict = new Dictionary<string, IList<int>>();
// assign values
dict["abc"] = new List<int> { 2, 4, 8 };
dict["def"] = new List<int> { 10, 12, 14 };
// get value
int dictDef2 = dict["def"][1];
Finally, I got it.
public static Dictionary<string, string[]> demo = new Dictionary<string, string[]>
{
{ "abc",
new string[]
{
"1",
"2"
}
},
{ "def",
new string[]
{
"3",
"4"
}
},
};
Contains check:
if (demo.ContainsKey("abc"))
{
}
Get the value(s):
demo["abc"][0]
Thanks for any help.
If you want to change existing array, you can try Linq:
using System.Linq;
...
public static string[][,] patterns = new string[][,] {...}
...
public Dictionary<string, string[]> patternsDict = patterns
.Select((value, index) => (
key : $"keyNameExample{index}",
value : value.OfType<string>().ToArray()))
.ToDictionary(pair => pair.key, pair => pair.value);
Note, that we have to convert (flatten) 2d array into ordinal one
If you want just to declare dictionary and fill it:
public Dictionary<string, string[]> patterns = new Dictionary<string, string[]>() {
{"keyExample1", new string[] { "1,2,3", "3,2,5" }},
{"keyExample1", new string[] { "4,4,3", "7,1,2" }},
};
public string[][,] patterns = new string[][,] { new string[,] { { "1,2,3" }, { "3,2,5" } }, new string[,] { { "4,4,3" }, { "7,1,2" } } };
Dictionary<string, string[,]> patternsDictionary = new Dictionary<string, string[,]>();
for (int i = 0; i < patterns.Length; i++)
{
patternsDictionary.Add(i.ToString(), patterns[i]);
}
Console.WriteLine(patternsDictionary["0"][0,1]); // Returns 2 - from { "1,2,3" }
I have seen people use yield return, although every time I try and use it in foreach it tells me something along the lines of: The body of CollectDictionary cannot be an iterator block because Dictionary<string, object> is not an interator interface type
I have a lot of methods line the following, is there a way to reduce boilerplate?
public Dictionary<string, object> CollectDictionary()
{
var configLines = File.ReadAllLines(_file).Where(IsValidConfigLine);
var configElements = new Dictionary<string, object>();
foreach (var configElement in configLines)
{
configElements.Add(configElement.Split("=")[0], configElement.Split("=")[1]);
}
return configElements;
}
You can reduce the amount of code by using .ToDictionary().
public Dictionary<string, object> CollectDictionary()
{
string[] configLines = new string[]
{
"foo1=bar1",
"foo2=bar2",
"foo3=bar3",
"foo4=bar4",
};
return configLines.Select(configElement => configElement.Split("="))
.ToDictionary(splt => splt[0], splt => (object)splt[1]);
}
This should return the following Dciotnary
{
{ "foo1", "bar1" },
{ "foo2", "bar2" },
{ "foo3", "bar3" },
{ "foo4", "bar4" }
}
I want to assign some static values to my KeyValuePair object.
private IEnumerable<KeyValuePair<string, string>> getCountries()
{
return new List<KeyValuePair<string, string>>()
{
{ "code1", "value1" },
{ "code2", "value2" }
};
}
But this is throwing nooverloaded method error.
return new List<KeyValuePair<string, string>>()
{
new KeyValuePair<string, string>("code1", "value1"),
new KeyValuePair<string, string>("code2", "value2"),
};
If you're using .NET Core 2.0+, you can use the slightly less verbose:
return new List<KeyValuePair<string, string>>()
{
KeyValuePair.Create("code1", "value1"),
KeyValuePair.Create("code2", "value2"),
};
In C# 9, you can use target-typed new to write this as:
return new List<KeyValuePair<string, string>>()
{
new("code1", "value1"),
new("code2", "value2"),
};
Or with Dictionary you can achieve desired initialization style
var pairs = new Dictionary<string, string>
{
{ "one", "first" },
{ "two", "second" },
}.ToList();
pairs.Should().BeOfType<List<KeyValuePair<string, string>>>(); // Pass
Notice, that if later in the code you are going to just enumerate list of key value pairs, then you can use dictionary without explicitly converting it to the list.
var pairs = new Dictionary<string, string>
{
{ "one", "first" },
{ "two", "second" },
}
// later somewhere in the code
foreach(var pair in pairs)
{
Console.WriteLine($"{pair.Key}: {pair.Value}")
}
If you are using values internally (inside class), you can use tuples.
private IEnumerable<(string Code, string Name)> GetCountries()
{
yield return ("code", "Earth");
yield return ("code", "Vulkan");
}
Which later can be consumed in more readable way
foreach(var country in GetCountries())
{
Console.WriteLine($"{country.Code}: {country.Name}")
}
If type used across application, then instead of using key-value pairs you can show intentions of your code to the readers of your code and create custom type.
public class Country
{
public string Code { get; }
public string Name { get; }
public Country(string code, string name)
{
Code = code;
Name = name;
}
}
private IEnumerable<Country> GetCountries()
{
yield return new Country("code", "Earth");
yield return new Country("code", "Vulkan");
}
Which later can be consumed in more readable way
foreach(var country in GetCountries())
{
Console.WriteLine($"{country.Code}: {country.Name}")
}
You need to consider that both Key and Value properties of the generic class are read-only, so you cannot set them directly. Instead you need to take advantage of the class's constructor in order to set the desired pairs.
public IEnumerable<KeyValuePair<string, string>> getCountries()
{
var keyValue1 = new KeyValuePair<string,string>("code1","value1");
var keyvalue2 = new KeyValuePair<string,string>("code2","value2");
var keyValueList = new List<KeyValuePair<string, string>> {keyValue1, keyvalue2};
return keyValueList;
}
I have a string List that contains some numbers .
I have some string in mybuylist that matches in Dictionary list. But this if condition always returns False. Ok mybuylist like [34,45,58] and mcollection(key,value) like this {[565,5]},{[34,1]},{[78,9]}....
public static Dictionary<string, int> mcollection = new Dictionary<string, int>();
public static List<string> mybuylist = new List<string>();
foreach (string entry in mybuylist) {
if (mcollection.ContainsKey(entry))
{
//dosomething
}
}
Hope someone help me about this
It might be the the problem of case-sensitive comparison or Keys are not matching. All Dictionaries are case-sensitive by default. A and a are different. Verify whether the values in mybuylist and mcollection are same or not.
Declare mcollection like below.
public static Dictionary<string, int> mcollection = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
This will ignorecase and A & a are same.
See this.
EDIT 1:
class Program
{
public static Dictionary<string, int> mcollection = new Dictionary<string, int>() { { "565", 5 }, { "34", 1 }, { "78", 9 } };
public static List<string> mybuylist = new List<string>() { "34", "45", "58" };
static void Main(string[] args)
{
foreach (string entry in mybuylist)
{
if (mcollection.ContainsKey(entry))
{
Console.WriteLine(entry);
//dosomething
}
}
}
}
O/P: 34
EDIT 2: Use below code to remove the spaces
mybuylist = mybuylist.ConvertAll(s => s.Trim());
I am trying to create a List of Dictionary<string,int> items. I am not sure how to add items in list and how to get back the values while traversing the list. I want to use it in C#, like so:
public List<Dictionary<string,int>> MyList= new List<Dictionary<string,int>>();
A lot has changed in 5 years... You can now do the following:
ListDictionary list = new ListDictionary();
list.Add("Hello", "Test1");
list.Add("Hello", "Test2");
list.Add("Hello", "Test3");
Enjoy!
I think this is what you are looking for?
{
MyList.Add(new Dictionary<string,int>()); // "Dictionary 1"
MyList.Add(new Dictionary<string,int>()); // "Dictionary 2"
MyList[0].Add("Dictionary 1", 1);
MyList[0].Add("Dictionary 1", 2);
MyList[1].Add("Dictionary 2", 3);
MyList[1].Add("Dictionary 2", 4);
foreach (var dictionary in MyList)
foreach (var keyValue in dictionary)
Console.WriteLine(string.Format("{0} {1}", keyValue.Key, keyValue.Value));
}
I think you have to know in which of the dictinaries you have to add your new value. So The List is the problem. You can't identify the dictionary inside.
My solution for this would be a dictionary collection class.
It could look like this:
public class DictionaryCollection<TType> : Dictionary<string,Dictionary<string,TType>> {
public void Add(string dictionaryKey,string key, TType value) {
if(!ContainsKey(dictionaryKey))
Add(dictionaryKey,new Dictionary<string, TType>());
this[dictionaryKey].Add(key,value);
}
public TType Get(string dictionaryKey,string key) {
return this[dictionaryKey][key];
}
}
then you can use it like this:
var dictionaryCollection = new DictionaryCollection<int>
{
{"dic1", "Key1", 1},
{"dic1", "Key2", 2},
{"dic1", "Key3", 3},
{"dic2", "Key1", 1}
};
// Try KeyValuePair Please.. Worked for me
private List<KeyValuePair<string, int>> return_list_of_dictionary()
{
List<KeyValuePair<string, int>> _list = new List<KeyValuePair<string, int>>();
Dictionary<string, int> _dictonary = new Dictionary<string, int>()
{
{"Key1",1},
{"Key2",2},
{"Key3",3},
};
foreach (KeyValuePair<string, int> i in _dictonary)
{
_list.Add(i);
}
return _list;
}