user3174976
user3174976

Reputation: 351

To simplify the Linq syntax for group, order and select top 1

I have several data in Deal class like the following one:

public class Deal
{
 public int Id {get;set;}
 public int SiteEdition {get;set;}
 public DateTime Date {get;set;}
}

I tried to group them by "Id" and "SiteEdition"; in each group, order by Date, and select top 1 data. My code is like:

    List<Deal> dealList = new List<Deal>();
    dealList.Add(new Deal(){Id=123, SiteEdition =1, Date = new DateTime(2017,6,1) });
    dealList.Add(new Deal(){Id=123, SiteEdition =1 , Date = new DateTime(2017,6,5) });
    dealList.Add(new Deal(){Id=123, SiteEdition =2 , Date = new DateTime(2017,6,9) });
    dealList.Add(new Deal(){Id=445, SiteEdition =1 , Date = new DateTime(2017,6,14) });
    dealList.Add(new Deal(){Id=445, SiteEdition =1 , Date = new DateTime(2017,6,19) });
    dealList.Add(new Deal(){Id=445, SiteEdition =2 , Date = new DateTime(2017,6,22) });
    dealList.Add(new Deal(){Id=445, SiteEdition =2 , Date = new DateTime(2017,6,25) });
    dealList.Add(new Deal(){Id=445, SiteEdition =3 , Date = new DateTime(2017,6,27) });
    dealList.Add(new Deal(){Id=445, SiteEdition =3 , Date = new DateTime(2017,6,29) });



    List<Deal> finalList = dealList.GroupBy(s=>new{s.Id,s.SiteEdition}).Select(y => new Deal{Id=y.OrderByDescending(m=>m.Date).First().Id, SiteEdition = y.OrderByDescending(m=>m.Date).First().SiteEdition, Date = y.OrderByDescending(m=>m.Date).First().Date}).ToList();
    foreach(var item in finalList)
    {
      Console.WriteLine("Id: " + item.Id + "; SiteEdition: " + item.SiteEdition + " ;DateTime: " + item.Date);
    }

It works fine but the linq syntax looks ugly, especially the parts of "y.OrderByDescending(m=>m.Date).First()"....

Is there any way to simplify this syntax?

Upvotes: 1

Views: 61

Answers (1)

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236218

You don't neet to create new instance of Deal. Just return one which you already have in the group.

You can use the fact that GroupBy preserves the order of the source sequence within the group - simply sort sequence only once and select first item from each group

dealList.OrderByDescending(d => d.Date)
        .GroupBy(d => new { d.Id, d.SiteEdition })
        .Select(g => g.First())
        .ToList()

Or you can sort each group separately

dealList.GroupBy(d => new { d.Id, d.SiteEdition })
        .Select(g => g.OrderByDescending(d => d.Date).First())
        .ToList()

Upvotes: 1

Related Questions