Convert List<MyObject> to Dictionary <obj.string, List<obj.ID>>
I would like to take a list of objects and convert it to a dictionary where the key is a field in the object, and the value is a list of a different field in the objects that match on the key. I can do this now with a loop but I feel this should be able to be accomplished with linq and not having to write the loop. I was thinking a combination of GroupBy
and ToDictionary
but have been unsuccessful so far.
Here's how I'm doing it right now:
var samplesWithSpecificResult = new Dictionary<string, List<int>>();
foreach(var sample in sampleList)
{
List<int> sampleIDs = null;
if (samplesWithSpecificResult.TryGetValue(sample.ResultString, out sampleIDs))
{
sampleIDs.Add(sample.ID);
continue;
}
sampleIDs = new List<int>();
sampleIDs.Add(sample.ID);
samplesWithSpecificResult.Add(sample.ResultString, sampleIDs);
}
The farthest I can get with .GroupBy().ToDictionay()
is 开发者_StackOverflow社区 Dictionary<sample.ResultString, List<sample>>
.
Any help would be appreciated.
Try the following
var dictionary = sampleList
.GroupBy(x => x.ResultString, x => x.ID)
.ToDictionary(x => x.Key, x => x.ToList());
The GroupBy
clause will group every Sample
instance in the list by its ResultString
member, but it will keep only the Id
part of each sample. This means every element will be an IGrouping<string, int>
.
The ToDictionary
portion uses the Key
of the IGrouping<string, int>
as the dictionary Key. IGrouping<string, int>
implements IEnumerable<int>
and hence we can convert that collection of samples' Id
to a List<int>
with a call to ToList
, which becomes the Value
of the dictionary for that given Key
.
Yeah, super simple. The key is that when you do a GroupBy
on IEnumerable<T>
, each "group" is an object that implements IEnumerable<T>
as well (that's why I can say g.Select
below, and I'm projecting the elements of the original sequence with a common key):
var dictionary =
sampleList.GroupBy(x => x.ResultString)
.ToDictionary(
g => g.Key,
g => g.Select(x => x.ID).ToList()
);
See, the result of sampleList.GroupBy(x => x.ResultString)
is an IEnumerable<IGrouping<string, Sample>>
and IGrouping<T, U>
implements IEnumerable<U>
so that every group is a sequence of Sample
with the common key!
Dictionary<string, List<int>> resultDictionary =
(
from sample in sampleList
group sample.ID by sample.ResultString
).ToDictionary(g => g.Key, g => g.ToList());
You might want to consider using a Lookup instead of the Dictionary of Lists
ILookup<string, int> idLookup = sampleList.ToLookup(
sample => sample.ResultString,
sample => sample.ID
);
used thusly
foreach(IGrouping<string, int> group in idLookup)
{
string resultString = group.Key;
List<int> ids = group.ToList();
//do something with them.
}
//and
List<int> ids = idLookup[resultString].ToList();
var samplesWithSpecificResult =
sampleList.GroupBy(s => s.ResultString)
.ToDictionary(g => g.Key, g => g.Select(s => s.ID).ToList());
What we 're doing here is group the samples based on their ResultString
-- this puts them into an IGrouping<string, Sample>
. Then we project the collection of IGrouping
s to a dictionary, using the Key
of each as the dictionary key and enumerating over each grouping (IGrouping<string, Sample>
is also an IEnumerable<Sample>
) to select the ID
of each sample to make a list for the dictionary value.
精彩评论