Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 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.

like image 456
Jace Rhea Avatar asked Dec 17 '09 22:12

Jace Rhea


2 Answers

    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.

like image 109
Marc Gravell Avatar answered Sep 20 '22 02:09

Marc Gravell


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.

like image 30
Greg Beech Avatar answered Sep 22 '22 02:09

Greg Beech