Query a dictionary in a dictionary with LINQ

I have a nested dictionary like this

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

      

With LINQ, I would like

  • Sort the external dictionary in descending order, keep the first 20 and work with the internal Dictionary.

  • Sort the internal dictionary in descending order, keep sorted, List<string>

    and perform operations on these lists of strings.

I have tried many things with no success.

+2


source to share


5 answers


One long line.



var result = dict.OrderByDescending(outer => outer.Key).Take(20).SelectMany(x =>
    x.Value).OrderByDescending(inner => inner.Key).Select(i => i.Value);

      

+5


source


For this kind of testing, I highly recommend [LINQPad] [1], it's free for the version without autocomplete. I started by populating the data with test data:

Dictionary<double, Dictionary<double, List<string>>> master
     = new Dictionary<double, Dictionary<double, List<string>>>();

for( double i = 1; i < 5; i += 0.25 )
{
    master[ i ] = new Dictionary<double, List<string>>();
    for( double j = 1; j < 5; j += 0.25 )
    {
        master[ i ][ j ] = new List<string>();
        master[ i ][ j ].Add( String.Format( "{0}-{1}a", i, j ) );
        master[ i ][ j ].Add( String.Format( "{0}-{1}b", i, j ) );
        master[ i ][ j ].Add( String.Format( "{0}-{1}c", i, j ) );
    }
}

      

LINQPad allows me to dump the output using a dedicated extension method Dump () (in this case, I set my type to "C # Statement (s)"):

master.Keys.Dump("Master keys");

      

Then I get the top 2 (for your data, of course you want the top 20, I just used a smaller test set).

var query1 = from di in master
            orderby di.Key descending
            select di;
query1.Take(2).Dump("Top 2 dictionaries (by key desc)");

      

Now I use this as the source for my next request:

var query2 = from di2 in query1.Take(2)
            from item in di2.Valuefrom di in master
            orderby di.Key descending
            select di
            orderby item.Key descending
            select item;
// show output
query2.Dump("Merged list");

      



You probably figured out that you can do it all as one query:

var query = from di2 in (
                from di in master
                orderby di.Key descending
                select di
            ).Take(2)
            from item in di2.Value
            orderby item.Key descending
            select item;

      

Finally, it's just a matter of what you want to do with that list, if you just want the lines in natural order for each parent to do this:

var stringList = from di in query
                from s in di.Value
                select s;
stringList.Dump("Strings only");

      

For my test data, here are the first dozens of items I got (don't want to list all 96 results):

4.75-4.75a
4.75-4.75b
4.75-4.75c
4.5-4.75a
4.5-4.75b
4.5-4.75c
4.75-4.5a
4.75-4.5b
4.75-4.5c
4.5-4.5a
4.5-4.5b
4.5-4.5c

      

Since I only dealt with the top 2 and not the top 20, I first got the items for the keys 4.5 and 4.75, then in this I sort by the second key getting all the values.

+1


source


Dictionaries not intended for sorting.

Having said that, this question contains a number of different word-sorting strategies. How do you sort a dictionary by value?

0


source


You can use 2 SortedDictionary and iterate over keys without using LINQ.

0


source


Dictionary<TKey, TValue>

implements IEnumerable<KeyValuePair<TKey, TValue>>

, allowing you to query your double / value pairs:

Dictionary<double, Dictionary<double, List<string>>> dict = GetDict();

IEnumerable<Dictionary<double, List<string>>> top20 = (
    from kvp in dict
    orderby kvp.Key descending
    select kvp.Value
    ).Take(20);

IEnumerable<List<string>> res =
    from d in top20
    from kvp in d
    orderby kvp.Key descending
    select kvp.Value;

      

0


source







All Articles