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?
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);
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 !!!
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.
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.