Ben H
Ben H

Reputation: 3236

Group items and select specific item from each group with 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!

Upvotes: 5

Views: 4577

Answers (1)

Ani
Ani

Reputation: 113402

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.

Upvotes: 6

Related Questions