如何在Linq的GroupBy中选择前N行

20

希望您能在这里帮助我。 我有一个Booking列表,我想在每个TourOperators组中获取前2行。

以下是数据样例:

List<Booking> list = new List<Booking>();
        list.Add(new Booking() { BookingNo = "31111111", DepDate = new DateTime(2011, 5, 1), TourOperator = "SPI" });
        list.Add(new Booking() { BookingNo = "32222222", DepDate = new DateTime(2011, 5, 2), TourOperator = "SPI" });
        list.Add(new Booking() { BookingNo = "33333333", DepDate = new DateTime(2011, 5, 3), TourOperator = "SPI" });
        list.Add(new Booking() { BookingNo = "34444444", DepDate = new DateTime(2011, 5, 4), TourOperator = "SPI" });
        list.Add(new Booking() { BookingNo = "35555555", DepDate = new DateTime(2011, 5, 5), TourOperator = "SPI" });
        list.Add(new Booking() { BookingNo = "36666666", DepDate = new DateTime(2011, 5, 6), TourOperator = "SPI" });
        list.Add(new Booking() { BookingNo = "11111111", DepDate = new DateTime(2011, 5, 1), TourOperator = "VIN" });
        list.Add(new Booking() { BookingNo = "12222222", DepDate = new DateTime(2011, 5, 2), TourOperator = "VIN" });
        list.Add(new Booking() { BookingNo = "13333333", DepDate = new DateTime(2011, 5, 3), TourOperator = "VIN" });
        list.Add(new Booking() { BookingNo = "14444444", DepDate = new DateTime(2011, 5, 4), TourOperator = "VIN" });
        list.Add(new Booking() { BookingNo = "15555555", DepDate = new DateTime(2011, 5, 5), TourOperator = "VIN" });
        list.Add(new Booking() { BookingNo = "16666666", DepDate = new DateTime(2011, 5, 6), TourOperator = "VIN" });
        list.Add(new Booking() { BookingNo = "17777777", DepDate = new DateTime(2011, 5, 7), TourOperator = "VIN" });

我有这个Linq查询,但它只给我每个组中的第一个Booking:

List<Booking> yetAnotherList = list.GroupBy(row => row.TourOperator)
            .Select(g => g.OrderBy(row => row.DepDate).First()).ToList();

我希望的数据如下所示:

31111111,2011-05-01,SPI
32222222,2011-05-02,SPI
11111111,2011-05-01,VIN
12222222,2011-05-02,VIN

谢谢。

2个回答

35

First()替换为Take(2)并使用SelectMany()

List<Booking> yetAnotherList = 
                 list.GroupBy(row => row.TourOperator)
                     .SelectMany(g => g.OrderBy(row => row.DepDate).Take(2)) 
                     .ToList();

更新: 第一次忘记了SelectMany。你想要展开结果(SelectMany可以实现),否则你会得到一个IEnumerables列表。


这给了我一个错误:无法隐式转换类型'System.Collections.Generic.List<System.Collections.Generic.IEnumerable<ConsoleApplication2.Booking>>'为 'System.Collections.Generic.List<ConsoleApplication2.Booking>'。 - M Raymaker
JensRud,请尝试使用var并在调试中查看yetAnotherList的类型。 - Sergey Metlov
哇,谢谢 Chris,SelectMany 和 Take 的组合正是我需要的!正如你指出的那样,结果需要展开。 - M Raymaker

1
尝试使用var,并将First()替换为Take(2):
var yetAnotherList = list.GroupBy(row => row.TourOperator)
                  .Select(g => g.OrderBy(row => row.DepDate).Take(2)).ToList(); 

1
JensRud说,在用Take(2)替换First()后,他遇到了一个异常。这是什么意思?我建议JensRud使用var来查看更详细的结果信息。我相信这样就不会出现异常了。 - Sergey Metlov
感谢您的回复Joolio,但它给了我两个嵌套列表,而我需要结果被展开。正如我从Chris的答案中发现的那样,SelectMany可以做到这一点。 - M Raymaker
应该将“Select”替换为“SelectMany”。 - bakunet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接