Iteratate Dictionay of List

  • Thread starter Thread starter Luigi
  • Start date Start date
L

Luigi

Hi all,
I have a dictionary like this:

Dictionary<List<string>, List<string>>

How can I iterate in it?

Thanks very much.
 
Well, what do you want to iterate? Each key (a List<string>) could have
multiple valies - do you just want the values?

With C# 3.0 / .NET 3.5, SelectMany is an option, but I guess (last post)
that this isn't an option. So you'll just need a few nested foreach loops.

Marc
 
Marc Gravell said:
Well, what do you want to iterate? Each key (a List<string>) could have
multiple valies - do you just want the values?

With C# 3.0 / .NET 3.5, SelectMany is an option, but I guess (last post)
that this isn't an option. So you'll just need a few nested foreach loops.

Yes, I'm using C# 2.0, so many useful options are prohibited for me.
What I'd like is to obtain the collection of strings for every string of the
first List in my dictionary.

Luigi
 
Yes, I'm using C# 2.0, so many useful options are prohibited for me.
What I'd like is to obtain the collection of strings for every string of the
first List in my dictionary.

Can you show that with a simple example?

i.e.
"if the data was as bloe, then I want {your bit here}

item 1: key (list) "a", "b"
value (list) "c", "d", "e"
item 2: key (list) "f"
value (list) "g", "h"

Marc
 
Marc Gravell said:
Can you show that with a simple example?

i.e.
"if the data was as bloe, then I want {your bit here}

item 1: key (list) "a", "b"
value (list) "c", "d", "e"
item 2: key (list) "f"
value (list) "g", "h"

I can't use the ContainsKey method of my Dictionary passing a List<string>
that is contained.

L
 
See below; I expect the problem is that you are passing a *different*
list that has the same data. By default, the lists are compared for
object (reference) equality. It is possible to override this behavior by
performing a custom comparison (so that two lists with the same contents
are treated as equal). Let me know if you need this.

Marc

class Program
{
static void Main()
{
Dictionary<List<string>, List<string>> lookup = new
Dictionary<List<string>, List<string>>();
lookup.Add(Wrap("a", "b"), Wrap("c", "d", "e"));
lookup.Add(Wrap("f"), Wrap("g", "h"));

List<string> firstKey = null;
foreach (KeyValuePair<List<string>, List<string>> pair in lookup)
{
if (firstKey == null) firstKey = pair.Key;
Write(pair.Key, "Key");
Write(pair.Value, "Value");
}

if (lookup.ContainsKey(firstKey))
{
List<string> value = lookup[firstKey];
Write(value, "Value By Key");
}
}
static void Write<T>(List<T> list, string caption)
{
Console.WriteLine(caption);
foreach (T t in list)
{
Console.WriteLine("\t{0}", t);
}
}
static List<T> Wrap<T>(params T[] args)
{
return new List<T>(args);
}
}
 
To treat different lists (with the same contents) as equal, you need to
provide a custom IEqualityComparer<T> to the dictionary's constructor.

The following should suffice, used with:

... lookup = new Dictionary<List<string>,
List<string>>(ListComparer<string>.Default);

Marc

class ListComparer<T> : IEqualityComparer<List<T>>
{
private readonly IEqualityComparer<T> itemComparer;
public static readonly ListComparer<T> Default = new ListComparer<T>();
public ListComparer() : this(null) { }
public ListComparer(IEqualityComparer<T> itemComparer)
{
this.itemComparer = itemComparer ?? EqualityComparer<T>.Default;
}

bool IEqualityComparer<List<T>>.Equals(List<T> x, List<T> y)
{
if (ReferenceEquals(x, y)) return true;
int len;
if (x == null || y == null || (len = x.Count) != y.Count)
return false;
for (int i = 0; i < len; i++)
{
if (!itemComparer.Equals(x, y)) return false;
}
return true;
}

int IEqualityComparer<List<T>>.GetHashCode(List<T> list)
{
if (list == null) return 0;
int agg = 3;
foreach (T item in list)
{
agg *= 13;
agg += 7 * itemComparer.GetHashCode(item);
}
return agg;
}
}
 
Are you sure you don't want something like

Dictionary<string, Dictionary<string, string>>

Your data structure seems quite useless to me. What are you intending to
store within it, and how do you intend to use that data?
 
Marc Gravell said:
See below; I expect the problem is that you are passing a *different*
list that has the same data. By default, the lists are compared for
object (reference) equality. It is possible to override this behavior by
performing a custom comparison (so that two lists with the same contents
are treated as equal). Let me know if you need this.

Marc

class Program
{
static void Main()
{
Dictionary<List<string>, List<string>> lookup = new
Dictionary<List<string>, List<string>>();
lookup.Add(Wrap("a", "b"), Wrap("c", "d", "e"));
lookup.Add(Wrap("f"), Wrap("g", "h"));

List<string> firstKey = null;
foreach (KeyValuePair<List<string>, List<string>> pair in lookup)
{
if (firstKey == null) firstKey = pair.Key;
Write(pair.Key, "Key");
Write(pair.Value, "Value");
}

if (lookup.ContainsKey(firstKey))
{
List<string> value = lookup[firstKey];
Write(value, "Value By Key");
}
}
static void Write<T>(List<T> list, string caption)
{
Console.WriteLine(caption);
foreach (T t in list)
{
Console.WriteLine("\t{0}", t);
}
}
static List<T> Wrap<T>(params T[] args)
{
return new List<T>(args);
}
}

Thank you Marc, very interesting.
Now I'm trying to using this code in my project.

Luigi
 
In the first string I have a name of check.
In the inner dictionary I have a list of objects that have to match together.
For example

"check1" is the key of the outer dictionary.

then I have "value1", "value2" is the key of the inner dic, and
"innervalue1", "innervalue2", "innervalue3" are the values.

Luigi
 
Another question Marc.
How can I write a methods that returns me the composition of the inner
dictionary?
For example, for the first KeyValuePair of the first List<string> I'd like
to obtain the List<string> value of the inner dictionary.

Luigi
 
Looks more like you want this...

Dictionary<string, Dictionary<string, List<string>>>


Take a look at this....


using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication7
{
class Program
{
static void Main(string[] args)
{
Dictionary<string, Dictionary<string, List<string>>> checks = new
Dictionary<string, Dictionary<string, List<string>>>();

for (int checkNumber = 0; checkNumber < 10; checkNumber++)
{
checks.Add("Check" + checkNumber.ToString(), CreateCheck());
}

foreach (var currentCheck in checks)
{
Console.WriteLine("CurrentCheck: " + currentCheck.Key);
foreach (var currentValue in currentCheck.Value)
{
Console.WriteLine(" Current value: " + currentValue.Key);
foreach (var currentInnerValue in currentValue.Value)
Console.WriteLine(" Current inner value: " + currentInnerValue);
Console.ReadLine();
}
}

}

private static Dictionary<string, List<string>> CreateCheck()
{
var result = new Dictionary<string, List<string>>();
for (int valueNumber = 0; valueNumber < 10; valueNumber++)
{
result.Add("Value" + valueNumber.ToString(), CreateInnerValues());
}
return result;
}

private static List<string> CreateInnerValues()
{
return new List<string>(new string[] { "One", "Two", "Three" });
}

}
}
 
Having this code:

Dictionary<string, Dictionary<string[], string[]>> outerCheck =
new Dictionary<string, Dictionary<string[], string[]>>();

Dictionary<string[], string[]> innerCheck = new Dictionary<string[],
string[]>();
string[] vociReference1 = {"Tava|a", "Tavb|b"};
string[] vociBalancing1 = {"Tavm|m", "Tavn|n"};

innerCheck.Add(vociReference1,vociBalancing1);

outerCheck.Add("Check1", innerCheck);

Dictionary<string[], string[]> innerCheckTest = new Dictionary<string[],
string[]>();
innerCheckTest = outerCheck["Check1"];

Dictionary<string[], string[]>.KeyCollection keys = innerCheckTest.Keys;

string[] myKeys;

I can't populate this array.
What's wrong?

L
 
Back
Top