7

Please can you advise me on how to query a Dictionary of Dictionaries, and/or a Dictionary of List?

private Dictionary<string, Dictionary<DateTime, double>> masterDict= new Dictionary<string, Dictionary<DateTime, double>>();

Private Dictionary<string, List<DateTime>> masterList= new Dictionary<string, List<DateTime>>();

I know if I do the following, I get a list of the dictionaries contained in masterDict, but I'm not sure how to get at the values of those dictionaries.

 foreach (var kvp in masterDictMethod())
        {
            Console.WriteLine("Key = {0}, Value = {1}",
                kvp.Key, kvp.Value);
        }

Thanks for looking ;)

Brian
  • 747
  • 3
  • 13
  • 22

5 Answers5

6

In you foreach kvp.Value is the inner dictionary of every masterDict entry i.e. Dictionary<DateTime, double>

So, just foreach also over kvp.Value and you will get the inner values.

e.g.

foreach (var kvp1 in masterDictMethod())
{
   Console.WriteLine("Key = {0}, Inner Dict:", kvp1.Key);
   foreach (var kvp2 in kvp1.Value)
   {
      Console.WriteLine("Date = {0}, Double = {1}", kvp2.Key, kvp2.Value);
   }
}
digEmAll
  • 56,430
  • 9
  • 115
  • 140
1

Use masterDict.Values

Aliostad
  • 80,612
  • 21
  • 160
  • 208
1

This one is:

var masterDictionary = new Dictionary<string, Dictionary<DateTime, double>>(); 

var query =
  from kvp1 in masterDictionary
  from kvp2 in kvp1.Value
  select new {TheString = kvp1.Key, TheDate = kvp2.Key, TheDouble = kvp2.Value };

foreach(var x in query)
{
  Console.WriteLine("{0} {1} {2}", x.TheString, x.TheDate, x.TheDouble);
}

And then the other one is:

var masterList= new Dictionary<string, List<DateTime>>(); 

var query =
  from kvp in masterList
  from val in kvp.Value
  select new {TheString = kvp.Key, TheDate = val);

foreach(var x in query)
{
  Console.WriteLine("{0} {1}", x.TheString, x.TheDate);
}
Amy B
  • 108,202
  • 21
  • 135
  • 185
0

You asked about lists, dictionaries and dictionaries containing other dictionaries.

I had a similar topic recently, where I wanted to have a queryable dictionary (i.e. an extension method which allows to pass a query expression as lambda parameter), that you can use like:

var result = myDictionary.QueryDictionary(w => myList.Any(a => a == w.Key));

The purpose of this code line is to check if any key of the dictionary is contained in myList.

So what I did is this, I wrote the following extension method:

// extension method using lambda parameters
public static Dictionary<string, T> QueryDictionary<T>(
    this Dictionary<string, T> myDict, 
    Expression<Func<KeyValuePair<string,T>, bool>> fnLambda)
{
    return myDict.AsQueryable().Where(fnLambda).ToDictionary(t => t.Key, t => t.Value);
}

It can be used for every dictionary which has keys of type string and items of every object type T.

Now you can easily write queries by passing a lambda expression, as in the following example:

var list1 = new List<string>() { "a", "b" };
var myDict = new Dictionary<string, object>();
myDict.Add("a", "123"); myDict.Add("b", "456"); myDict.Add("c", "789"); 

var result = myDict.QueryDictionary(w => list1.Any(a => a == w.Key));

The result will contain items a and b, because they are contained in list1.

You can also query a dictionary of dictionaries, here's a C# example for LinqPad, but it can be used as a console application as well (just comment out the .Dump() statements and replace them by Console.WriteLine(...) statements):

void Main()
{
    // *** Set up some data structures to be used later ***
    var list1 = new List<string>() { "a", "b", "d" }; // a list
    var myDict = new Dictionary<string, object>(); // the dictionary
    myDict.Add("a", "123"); myDict.Add("b", "456"); myDict.Add("c", "789"); 

    var myDict2 = new Dictionary<string, object>(); // 2nd dictionary
    myDict2.Add("a", "123"); myDict2.Add("b", "456"); myDict2.Add("c", "789"); 

    myDict.Add("d", myDict2); // add 2nd to first dictionary

    // *** 1. simple query on dictionary myDict ***
    var q1 = myDict.QueryDictionary(w => list1.Any(a => a == w.Key));
    q1.Dump();

    // *** 2. query dictionary of dictionary (q3 contains result) ***
    var q2 = 
      (Dictionary<string, object>)q1.QueryDictionary(w => w.Key.Equals("d")).First().Value; 
    var q3 = q2.QueryDictionary(w => w.Key.Equals("b"));
    q3.Dump();
}

// *** Extension method 'QueryDictionary' used in code above ***
public static class Extensions
{
    public static Dictionary<string, T> QueryDictionary<T>(
       this Dictionary<string, T> myDict, 
       Expression<Func<KeyValuePair<string, T>, bool>> fnLambda)
    {
        return myDict.AsQueryable().Where(fnLambda).ToDictionary(t => t.Key, t => t.Value);
    }
}

Since this solution is using Generics, you can pass any lambda expression as search parameter, so it is very flexible.

Matt
  • 25,467
  • 18
  • 120
  • 187
0
foreach (var key in masterDict.Keys)
{
    var nestedDict = masterDict[key];
}
Philippe
  • 3,945
  • 3
  • 38
  • 56
  • Would be better to do: `foreach (var kv in masterDict) { /* work with kv.Value - the inner dict. */ }`. This saves the inner lookup (`Dictionary` implements `IEnumerable>`.) – Richard Sep 16 '10 at 12:21