How to iterate through List of Dictionaries? - c#

I have the following code :
List<Dictionary<string, string>> allMonthsList = new List<Dictionary<string, string>>();
while (getAllMonthsReader.Read()) {
Dictionary<string, string> month = new Dictionary<string, string>();
month.Add(getAllMonthsReader["year"].ToString(),
getAllMonthsReader["month"].ToString());
allMonthsList.Add(month);
}
getAllMonthsReader.Close();
Now I'm trying to loop through all of the months, like this :
foreach (Dictionary<string, string> allMonths in allMonthsList)
How do I access the key values? Am I doing something wrong?

foreach (Dictionary<string, string> allMonths in allMonthsList)
{
foreach(KeyValuePair<string, string> kvp in allMonths)
{
string year = kvp.Key;
string month = kvp.Value;
}
}
BTW year usually has more than one month. Looks like you need a lookup here, or Dictionary<string, List<string>> for storing all months of year.
Explanation generic dictionary Dictionary<TKey, TValue> implements IEnumerable interface, which returns an enumerator that iterates through the collection. From msdn:
For purposes of enumeration, each item in the dictionary is treated as
a KeyValuePair<TKey, TValue> structure representing a value and its
key. The order in which the items are returned is undefined.
The foreach statement of the C# language requires the type of each element in the collection.
Since the Dictionary<TKey, TValue> is a collection of keys and values,
the element type is not the type of the key or the type of the value.
Instead, the element type is a KeyValuePair<TKey, TValue> of the key
type and the value type.

var months = allMonthsList.SelectMany(x => x.Keys);
You can then iterate through the IEnumerable<string> as you please which is a simple enumeration of all your keys.

Your design is wrong. Using one pair in dictionary is meaningless. You don't need to use list of dictionary.
Try this:
class YearMonth
{
public string Year { get; set; }
public string Month { get; set; }
}
List<YearMonth> allMonths = List<YearMonth>();
while (getAllMonthsReader.Read())
{
allMonths.Add(new List<YearMonth> {
Year = getAllMonthsReader["year"].ToString(),
Month = getAllMonthsReader["month"].ToString()
});
}
getAllMonthsReader.Close();
Use as:
foreach (var yearMonth in allMonths)
{
Console.WriteLine("Year is {0}, Month is {1}", yearMonth.Year, yearMonth.Month);
}
or, if you use .Net framework 4.0 or above, you can use Tuple
List<Tuple<string, string>> allMonths = List<Tuple<string, string>>();
while (getAllMonthsReader.Read())
{
allMonths.Add(Tuple.Create( getAllMonthsReader["year"].ToString(),
getAllMonthsReader["month"].ToString())
);
}
getAllMonthsReader.Close();
Then use:
foreach (var yearMonth in allMonths)
{
Console.WriteLine("Year is {0}, Month is {1}", yearMonth.Item1, yearMonth.Item2);
}

Related

Equivalent of java.lang.Number in C#

I want to make arithmetic operations between dictionaries with numbers as value.
This is my code:
public class DictionaryOperation {
public static Dictionary<TKey, double> Add<TKey>(Dictionary<TKey, double> d1, Dictionary<TKey, double> d2) {
Dictionary<TKey, double> result = new Dictionary<TKey, double>();
foreach (TKey key in d1.Keys) {
if (d2.ContainsKey(key))
result[key] = d1[key] + d2[key];
else
result[key] = d1[key];
}
foreach (TKey key in d2.Keys) {
if (!result.ContainsKey(key))
result[key] = d2[key];
}
return result;
}
}
I would like to know if I can create only one method for any numeric type (int float, decimal, ...) or do I have to create one method per numeric type, which means there will be the same code in each methods.
I want to be able to do this:
Dictionary<string, int> ints = DictionaryOperation.Add(new Dictionary<string, int>(), new Dictionary<string, int>());
Dictionary<string, float> floats = DictionaryOperation.Add(new Dictionary<string, float>(), new Dictionary<string, float>());
You can avoid writing the same Method for every numeric type by using generics. You already have a generic key in your dictionary. The only thing missing is the generic value. Change your method to use a generic dictionary value:
public static Dictionary<TKey, TValue> Add<TKey, TValue>(Dictionary<TKey, TValue> d1, Dictionary<TKey, TValue> d2)
where TValue : IComparable
The problem is, that there is no type constraint that allows only numbers (or objects that can be added with the + operator). I used IComparable in the line above because all numeric types are comparable.
The next problem is, the IComparable does not help when trying to use the + operator. For this you can use dynamics like so:
dynamic a = d1[key];
dynamic b = d2[key];
result[key] = a + b;
Now you can use the method for all types that implement IComparable. BUT you have no compile time safety. That means you will get runtime errors for all types that do not implement the + operator.
This problem is already described here:
C# Adding two Generic Values
Here the full method:
public static Dictionary<TKey, TValue> Add<TKey, TValue>(Dictionary<TKey, TValue> d1, Dictionary<TKey, TValue> d2)
where TValue : IComparable
{
Dictionary<TKey, TValue> result = new Dictionary<TKey, TValue>();
foreach (TKey key in d1.Keys) {
if (d2.ContainsKey(key))
{
dynamic a = d1[key];
dynamic b = d2[key];
result[key] = a + b;
}
else
result[key] = d1[key];
}
foreach (TKey key in d2.Keys) {
if (!result.ContainsKey(key))
result[key] = d2[key];
}
return result;
}

C# - Alternative to Dictionary<string, dynamic> for older versions?

I'm trying to implement a templating class that takes in a template ID and a Dictionary with the needed objects.
e.g.
public string GenerateMessage(string messageID, Dictionary<string, dynamic> values)
{
string gameMessage = gameMessages[messageID];
var template= new StringTemplate(gameMessage);
foreach (var value in values)
{
template.SetAttribute(value.Key, value.Value);
}
return template.ToString();
}
usage example
var values = new Dictionary<string, dynamic>();
values.Add("city", london) // instance of City
values.Add("country", uk) // instance of Country
values.Add("user", user) // instance of User
string message = GenerateMessage("ID123", values);
Unfortunately I'm using Unity and it only supports a subset of .NET 3.5, which doesn't include dynamic!
I really don't want to have a Dictionary<string, string> where I have to specify all the values I need, I would like to offer the templates references to the whole objects so that they can I can change the templates around with more flexibility.
Any ideas?
I don't know what gameMessage or StringTemplate is, however, maybe you can use generics:
public string GenerateMessage<T>(string messageID, Dictionary<string, T> values)
{
string gameMessage = gameMessages[messageID];
var template = new StringTemplate(gameMessage);
foreach (var value in values)
{
template.SetAttribute(value.Key, value.Value);
}
return template.ToString();
}

Adding Elements of generic list to dictionary

I have a generic list List<String, String> ListName
I am trying to insert the values of the list, into a dictionary Dictionary<String, int>
I looked at places but only found adding elements of dictionary to list. While my requirement is opposite. I tried using toDictionary, but it didnt work for me. Not sure what went wrong.
Have anyone every attempted inserting values from list to dictionary?
I assume you mean List<string[]> because I have never seen a generic List<T,WhoAmI> before
If you are using List<string[]> you can use the ToDictionary function
List<string[]> ListName = new List<string[]>();
ListName.Add(new[] { "Stack", "1" });
ListName.Add(new[] { "Overflow", "2" });
// Select the first string([0]) as the key, and parse the 2nd([1]) as int
Dictionary<string,int> result = ListName.ToDictionary(key => key[0], value => int.Parse(value[1]));
if you are using some kind of custom object in your list you can also do it the same way
List<MyObject<string, string>> ListName = new List<MyObject<string, string>>();
Dictionary<string, int> result = ListName.ToDictionary(key => key.String1, value => int.Parse(value.String2));
public class MyObject<T, U>
{
public MyObject(T string1, U string2)
{
String1 = string1;
String2 = string2;
}
public T String1 { get; set; }
public U String2 { get; set; }
}
Note: You should add error checking around the int.Parse or use Int.TryParse if there is a chance it may not be a number.
You can use like that:
List<KeyValuePair<String, String>> ListName = new List<KeyValuePair<String, String>>();
Dictionary<String, Int32> dict = new Dictionary<String, Int32>();
ListName.ForEach(e=> dict.Add(e.key, Int32.Parse(e.Value)));
I'm not sure exactly where the integer is coming from, but something like this should work:
Dictionary<string, int> dict = new Dictionary<string, int>();
list.ForEach(x => dict.Add(x, theInteger));

How to insert element in first index in dictionary?

Is there a method or technique that allows you to insert an element into a
Dictionary<TKey, TValue> guaranteeing that the item is in the first index of that dictionary's KeyCollection.
For example:
Dictionary<String, String> dic = foo.GetOutput();
// `dic` is something like:
// {"foo", "baa"},
// {"a", "b"}
I need something like:
dic.Add("key", "value", 0);
// where `0` is the index that `key` to be inserted.
foreach(KeyValuePair<String, String> key in dic)
{
Console.WriteLine("{0} = {1}", key.Key, key.Value);
}
Output:
key = value
foo = baa
a = b
By not using a dictionary.
Dictionary<TKey, TValue> is implemented as a hash-table. The position of keys internal to the dictionary depends upon the hash-code, the means by which that hash-code was reduced further to provide an index into its internal structure, and the order of insertion in an entirely implementation-dependant way.
This isn't the only way to implement a dictionary. SortedDictionary<TKey, TValue> uses a tree structure internally and so always keeps keys in an order. In this case we still can't insert something in the beginning, rather we insert something and it gets put in the appropriate place.
If ordering is what you care about most, then you don't want a puredictionary at all. Rather you want either a List<KeyValuePair<TKey, TValue>> or you want a structure that offers both the functionality of a list and of a dictionary, which is provided by OrderedDictionary. This isn't generic, but you can easily create a generic wrapper around it (doesn't give the performance benefits of internally using generics, but does give type-safety in use).
I know it is a three years old question. But found a workaround of this problem. It may help someone
Dictionary<String, String> dic = foo.GetOutput();
dic = (new Dictionary<string, string> {{"key","value"}}).Concat(dic).ToDictionary(k => k.Key, v => v.Value);
This will insert the element in the beginning of dictionary :)
Dictionaries are unordered; elements are meant to be retrieved with a key, whose hash points to its value's location.
What you might want is a List <KeyValuePair>, whose elements can be inserted into a specific index.
List<KeyValuePair<string, string>> list = dic.ToList();
list.Insert(0, new KeyValuePair<string, string>("a", "b"));
foreach(KeyValuePair<string, string> pair in list)
Console.WriteLine("{0} = {1}", pair.Key, pair.Value);
This is not possible with Dictionary<TKey, TValue> as it presents it's values in an unordered fashion when enumerated. There is SortedDictionary<TKey, TValue> which provides ordering but it does so by using an IComparer<TKey> against the key value directly. Here you want the key to be a String and have ordering based on an int. That is not possible with either of these types.
I think you'll need to implement a new type with these very specific semantics in them. For example.
class OrderedMap<TKey, TValue> {
private readonly Dictionary<TKey, TValue> _map = new Dictionary<TKey, TValue>();
private readonly List<TKey> _list = new List<TKey>();
public void Add(TKey key, TValue value) {
if (!_map.ContainsKey(key)) {
_list.Add(key);
}
_map[key] = value;
}
public void Add(TKey key, TValue value, int index) {
if (_map.ContainsKey(key)) {
_list.Remove(key);
}
_map[key] = value;
_list.Insert(index, key);
}
public TValue GetValue(TKey key) {
return _map[key];
}
public IEnumerabe<KeyValuePair<TKey, TValue>> GetItems() {
foreach (var key in _list) {
var value = _map[key];
yield return new KeyValuePair<TKey, TValue>(key, value);
}
}
}
Note this does come with some non-trivial performance differences over a traditional Dictionary<TKey, TValue>. For example Add and Remove are slower.
Dictionary<TKey, TValue> is inherently unordered (or rather, the ordering is unpredictable and shouldn't be relied upon). If you want some sort of ordering, you need to use a different type. It's hard to recommend any particular type without knowing more about your requirements.
The Dictionary<TKey, TValue> can't be ordered.
You can try SortedDictionary<TKey, TValue> instead, but that one is ordered by the Key, not by a separate index.
The Dictionary<TKey,TValue> class does not hold items in an ordered manner, so there is no "first" item.
There is a SortedDictionary<Tkey,TValue> (.NET 4.0+), which sorts by the key, but again, this is a very vague idea of "first".
this is my solution, maybe not the best solution but it works. =)
public static ComboBox FillDropDownList(Dictionary<String, String> dictionary, ComboBox dropDown, String selecione)
{
var d = new SortedDictionary<String, String>();
d.Add("0", selecione);
foreach (KeyValuePair<string, string> pair in dictionary)
{
d.Add(pair.Key, pair.Value);
}
dropDown.DataSource = new BindingSource(d, null);
dropDown.DisplayMember = "Value";
dropDown.ValueMember = "Key";
dropDown.SelectedIndex = 0;
return dropDown;
}
A Dictionary is an un-ordered collection. You could try OrderedDictionary - http://msdn.microsoft.com/en-us/library/system.collections.specialized.ordereddictionary.aspx - which has an Insert() method which is what you're after.

Question on using List

I created an List like this
List<Dictionary<DicKeyCla, DicValCla>>
public Class DicKeyCla
{
public EnKey1 DicKeyItem1,
public EnKey2 DicKeyItem2,
}
public enum EnKey1
{
A1,
A2,
A3,
A4,
A5
}
public enum EnKey2
{
B11,
B12,
B13,
B14,
B15,
B16,
B17,
B18,
B19,
}
As I know, there is contains() method available for List class.
If I called an function which argues contain the DicKeyCla members like A3 and B15.
How can I pick out the entirely dictionary member from the Top level List rapidly?
I need do more operation on dictionary member.
Here's the easy way to do it:
public static Dictionary<DicKeyCla, DicValCla>
FindDict(List<Dictionary<DicKeyCla, DicValCla>> haystack,
DicKeyCla needle)
{
foreach (Dictionary<DicKeyCla, DicValCla> dict in haystack)
if (dict.ContainsKey(needle))
return dict;
return null;
}
Given a list of dictionaries and a key, it will return the first dictionary that has that key, or null if none in the list do.
Or more generically:
public static IDictionary<TKey, TValue>
FindDict<TKey, TValue>(IEnumerable<IDictionary<TKey, TValue>> haystack,
TKey needle)
{
foreach (IDictionary<TKey, TValue> dict in haystack)
if (dict.ContainsKey(needle))
return dict;
return null;
}
If you need to do this lookup frequently or the list is very long, you may need to index your keys with a Dictionary<DicKeyCla, Dictionary<DicKeyCla, DicValCla>> that holds which dictionary contains which key. If multiple dictionaries can contain the same key then you would need a Dictionary<DicKeyCla, List<Dictionary<DicKeyCla, DicValCla>>> to store your index.
If you already have the list and want to create an index, you could do this:
Dictionary<DicKeyCla, Dictionary<DicKeyCla, DicValCla>> index =
new Dictionary<DicKeyCla, Dictionary<DicKeyCla, DicValCla>>();
foreach (Dictionary<DicKeyCla, DicValCla> dict in list)
foreach (KeyValuePair<DicKeyCla, DicValCla> item in dict)
index[item.Key] = dict;
// or in LINQ
Dictionary<DicKeyCla, Dictionary<DicKeyCla, DicValCla>> index =
(from dict in list
from item in dict
select new { item.Key, dict })
.ToDictionary(e => e.Key, e => e.dict);
And here's how you'd use the index:
public static Dictionary<DicKeyCla, DicValCla>
FindDict(Dictionary<DicKeyCla, Dictionary<DicKeyCla, DicValCla>> index,
DicKeyCla needle)
{
Dictionary<DicKeyCla, DicValCla> result;
index.TryGetValue(needle, out result);
return result;
}
The List.Contains method would only check if the parameter you send it is an item in the list.
If you want to be able to find an entire dictionary that contains some given A3 or B15 from this data strcuture, you will have to implement this yourself.
You can do something like manage an internal dictionary that would keep mapping from various A3/B15/etc objects to Lists of Dictionaries to which they have been added.
If O(1) search is not very important to you, consider favoring simplicity over performance, and just scan the list.
I have a strange feeling (but I'm probably wrong) that you wrapped your Dictionary with a List hoping you could search the 1 instance of the dictionary with the Contains method and all you want is to access the dictionary members by a combination of EnKey1 and EnKey2. Something like this:
public struct Key // note the struct...
{
public static Key A(EnKey1 k1, EnKey2 k2)
{
Key k = new Key();
k.Key1 = k1;
k.Key2 = k2;
return k;
}
public EnKey1 Key1;
public EnKey2 Key2;
}
Dictionary<Key, string> dic = new Dictionary<Key, string>();
dic.Add(Key.A(EnKey1.A1,EnKey2.B19), "test");
Console.WriteLine(dic[Key.A(EnKey1.A1,EnKey2.B19)]);
// outputs "test"
// then you can do:
// dic.ContainsKey(Key.A(EnKey1.A1,EnKey2.B19)) -> true
// dic.ContainsKey(Key.A(EnKey1.A2,EnKey2.B19)) -> false

Categories

Resources