获取第一个项目和最后一个项目(如果它存在于组中)

时间:2015-07-21 21:26:13

标签: linq entity-framework group-by

我的情况是我的数据看起来像这样。

Books
---------------------------------
title            | returnedDate
Great Gatsby     | 2015-05-04
Great Gatsby     | 2015-03-22
Great Gatsby     | 2015-01-11
Life of PI       | 2015-04-04
Life of PI       | 2015-04-02
Clean Code       | 2015-06-05

我想在单个linq语句中返回每个组中的第一本和最后一本书(按标题分组)。我知道我可以使用像这样的linq查询获得第一个或最后一个项目。

GitHub

如果最后一个项目存在,我怎样才能得到它?

我的最终结果如下:

Books
---------------------------------
title            | returnedDate
Great Gatsby     | 2015-05-04
Great Gatsby     | 2015-01-11
Life of PI       | 2015-04-04
Life of PI       | 2015-04-02
Clean Code       | 2015-06-05

3 个答案:

答案 0 :(得分:3)

var books = dbContext.Books
    .GroupBy(b => b.title)
    .Select(g=>new {
       Title=g.Key,
       First=g.OrderByDescending(x=>x).FirstOrDefault(),
       Last=g.OrderBy(x=>x).FirstOrDefault()
     });

Results:
title                  | First | Last 
Great Gatsby | 2015-05-04 | 2015-01-11
Life of PI         | 2015-04-04 | 2015-04-02
Clean Code    | 2015-06-05 | 2015-06-05

如果你真的想要它,就像你问的那样,那就变得有点困难了:

var books = dbContext.Books
    .GroupBy(b => b.title)
    .Select(g=>new {
       title=g.Key,
       returnedDate=g.OrderByDescending(x=>x).FirstOrDefault()
     }).Concat(
      dbContext.Books
      .GroupBy(b => b.title)
      .Where(g=>g.Count()>1)
      .Select(g=>new {
         title=g.Key,
         returnedDate=g.OrderBy(x=>x).FirstOrDefault()
       })
      ).OrderBy(c=>c.title).ThenDescendingBy(c=>c.returnedDate);

呸。可能是一种更好的方式,但首先想到的是。

答案 1 :(得分:2)

通过获取第一个和最后一个返回日期然后返回返回日期等于这些的书籍,可以实现:

from b in dbContext.Books
group b by b.title into bg
let first = bg.OrderByDescending (b => b.returnedDate).FirstOrDefault().returnedDate
let last = bg.OrderBy (b => b.returnedDate).FirstOrDefault().returnedDate
from b in bg
where b.returnedDate == first || b.returnedDate == last
orderby b.title, b.returnedDate
select b

答案 2 :(得分:0)

有点摆弄我想出了这个。不知道在处理大型数据表时这会有多高效。

        [Test]
    public void FirstLastLinq()
    {
        var books = new List<Book> 
        { 
            new Book { Title = "Great Gatsby", Returned=new DateTime(2015,04,03) },
            new Book { Title = "Great Gatsby", Returned=new DateTime(2015,04,02) },
            new Book { Title = "Great Gatsby", Returned=new DateTime(2015,04,01) },
            new Book { Title = "Life of PI", Returned=new DateTime(2015,03,05) },
            new Book { Title = "Life of PI", Returned=new DateTime(2015,03,04) },
            new Book { Title = "Clean Code", Returned=new DateTime(2015,02,02) },
        };

        var newBooks = books.GroupBy(b => b.Title).SelectMany(g => g.OrderByDescending(b => b.Returned)
            .Where(b1 => b1.Returned == g.Min(b2 => b2.Returned) || 
                (b1.Returned == g.Max(b3 => b3.Returned) && g.Min(b4 => b4.Returned) != g.Max(b5 => b5.Returned))));

        Assert.IsNotNull(newBooks);

    }
    private class Book 
    {
        public string Title { get; set; }
        public DateTime Returned { get; set; }
    }