user57508
user57508

Reputation:

Create a dictionary on a list with grouping

I have the following object in a list:

public class DemoClass
{
    public int GroupKey { get; set; }
    public string DemoString { get; set; }
    public object SomeOtherProperty { get; set; }
}

Now, I want to create following dictionary out of it:

Dictionary<int, List<DemoClass>>

I want to group the List<DemoClass> by the property GroupKey, but I don't understand how this is done and some help.

After thinking a bit, I achieved the needed behaviour with:

var groupedDemoClasses = from demoClass in mySepcialVariableWhichIsAListOfDemoClass
                            group demoClass by demoClass.GroupKey
                            into groupedDemoClass
                            select groupedDemoClass;
var neededDictionary = groupedDemoClass.ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

but, is there a way to make this into a single statement?

Upvotes: 121

Views: 84162

Answers (4)

Prashant Cholachagudda
Prashant Cholachagudda

Reputation: 13092

var groupedDemoClasses = (from demoClass in mySepcialVariableWhichIsAListOfDemoClass
                          group demoClass by demoClass.GroupKey
                          into groupedDemoClass
                          select groupedDemoClass).ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

This one will work !!!

Upvotes: 93

Mark
Mark

Reputation: 9428

I'm going slightly off topic here, but I got to this thread becausde I was looking for a way to create a dictionary of a dictionary in Linq, and the conversation here lead me to the answer...

You can use linq to create multi-level dictionaries, which is useful for scenarios where you've got more than 1 key or dimension that you want to search by. The trick is to create a grouping and then convert it to a dictionary, as follows:

  Dim qry = (From acs In ActualSales _
             Group By acs.ProductID Into Group _
             Select ProductID, Months = Group.ToDictionary(Function(c) c.Period) _
            ).ToDictionary(Function(c) c.ProductID)

The resulting query can be used as follows:

 If qry.ContainsKey(_ProductID) Then
      With qry(_ProductID)
          If .Months.ContainsKey(_Period) Then
             ...
          End If
      End With
 End If

Hope this is helpful to anyone else who needs this sort of query.

Upvotes: 4

Jon Skeet
Jon Skeet

Reputation: 1500215

Just to make mquander's suggestion concrete:

var groupedDemoClasses = mySpecialVariableWhichIsAListOfDemoClass
                             .GroupBy(x => x.GroupKey)
                             .ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

You'd make it shorter if you used shorter variable names too, of course :)

However, might I suggest that a Lookup might be more appropriate? A Lookup is basically a dictionary from a key to an IEnumerable<T> - unless you really need the values as a list, it makes the code even shorter (and more efficient) with the ToLookup call:

var groupedDemoClasses = mySpecialVariableWhichIsAListOfDemoClass
                             .ToLookup(x => x.GroupKey);

Upvotes: 221

mqp
mqp

Reputation: 71935

You already made it a one-liner. Just put the ToDictionary at the end of your first line. If you want it to be shorter, use the functional composition syntax instead of the query syntax.

Upvotes: 7

Related Questions