Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Group items and select specific item from each group with LINQ

Tags:

c#

linq

There has got to be a one-liner to do this, and I just can't find it.

Given this query:

from x in new XPQuery<XPContent>(s)
select new { x.Category, x.ContentType, x.Name, x.ContentID, x.Date }

I need to select the record with the greatest date for each distinct ContentID. Can this be done cleverly with LINQ? Right now I'm doing this:

var q = (from x in new XPQuery<XPContent>(s)
            select new { x.Category, x.ContentType, x.Name, x.ContentID, x.Date }).ToList();

var r = q.ToLookup(item => item.ContentID);
foreach (var rItem in r) {
    var s = rItem.OrderByDescending(a => a.Date).First();
    /* do stuff with s */
}

... but the ToLookup feels kind of clunky. Or do I have the best (simplest) solution?

Also, I know I shouldn't be using ToList, but please just ignore that for the time being.

Thanks in advance!

like image 931
Ben H Avatar asked Feb 16 '11 06:02

Ben H


1 Answers

I think you want:

var q = from x in new XPQuery<XPContent>(s)
        group x by x.ContentID into g
        let latest = g.OrderByDescending(a => a.Date).First()
        select new 
        {
            latest.Category, latest.ContentType,
            latest.Name, latest.ContentID, latest.Date
        };

(Do note that there are more performant ways of finding the 'maximum' element from a group than by sorting it first, for example with a MaxBy operator.)

The query is quite simple; it just groups items by their ContentId, and then from each group, selects an instance of an anonymous type that is produced from the group's latest item.

like image 122
Ani Avatar answered Sep 20 '22 16:09

Ani