Help Linqifying collection to Dictionary
I'm refactoring this code and was trying to think of a simple linq expression to populate this Dictionary.
IEnumerable<IHeaderRecord> headers = PopulateHeaders();
var headerLocationLookup = new Dictionary<string, IHeaderRecord>();
foreach (var header in headers)
{
//destination locations can repeat, if they do, dictionary should only contain the first header associated with a particular location
if (!headerLocationLookup.ContainsKey(header.DestinationLocation))
{
headerLocationLookup[header.DestinationLocation] = header;
}
}
I could only come up with implementing a开发者_StackOverflow custom IEqualityComparer and using that in an expression such as this...
headers.Distinct(new CustomComparer()).ToDictionary();
Is there a way to do it all inline without the custom IEqualityComparer? Thanks in advance.
var qry = headers.GroupBy(row => row.DestinationLocation)
.ToDictionary(grp => grp.Key, grp => grp.First());
or (equivalent):
var dictionary = (from row in headers
group row by row.DestinationLocation)
.ToDictionary(grp => grp.Key, grp => grp.First());
I wonder, though, if your current foreach
code isn't already better - it doesn't buffer the ones it intends to drop, for example.
I wrote a blog post a while back that shows you how you can create overloads of Distinct that use a lambda expression as the key selector instead of a custom comparer, which would let you write:
headers.Distinct(h => h.DestinationLocation)
.ToDictionary(h => h.DestinationLocation);
It does use a custom comparer underneath, but the extension method constructs that stuff for you, and makes it much easier to read.
var headerLocationLookup = PopulateHeaders()
.Aggregate(new Dictionary<string, IHeaderRecord>(), (header, d) => {
if(d.ContainsKey(header.DestinationLocation))
d[header.DestinationLocation] = header;
return d;
});
I don't think this is any clearer than the existing code though.
精彩评论