2011-04-24 5 views
10

espérons que vous pouvez m'aider ici. J'ai une liste de réservations où je voudrais obtenir les 2 premières rangées dans chaque groupe de TourOperators.Comment sélectionner les N premières lignes dans un groupe LinqPar

est ici un échantillon des données:

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" }); 

Je cette Linq, mais il me donne seulement la première réservation dans chaque groupe:

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

Les données que j'espérais était quelque chose comme ceci:

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

Merci.

Répondre

17

Remplacer First() avec Take(2) et utiliser SelectMany():

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

Mise à jour: Vous avez oublié le SelectMany la première fois. Vous voulez aplatir le résultat (ce que fait SelectMany), sinon vous obtenez une liste de IEnumerables.

+0

Cela me donne: Impossible de convertir implicitement le type « System.Collections.Generic.List > 'à' System.Collections.Generic.List ' –

+0

JensRud, essayez d'utiliser var et de voir dans le débogage quel type a encoreAnotherList. –

+0

Wow, merci Chris, la combinaison de SelectMany et Take était exactement ce dont j'avais besoin! Les résultats ont dû être aplatis comme vous l'avez souligné. –

1

Essayez d'utiliser var et remplacer First() avec Take(2):

var yetAnotherList = list.GroupBy(row => row.TourOperator) 
        .Select(g => g.OrderBy(row => row.DepDate).Take(2)).ToList(); 
+1

JensRud dit, qu'il a une exception après avoir remplacé First() par Take (2). Que voulez-vous dire!? J'ai conseillé à JensRud d'utiliser var pour avoir la possibilité de voir des informations plus détaillées sur le résultat. Je suis sûr que ce ne sera pas une exception. –

+0

Merci pour votre réponse Joolio, seulement cela me donne deux listes imbriquées, et j'ai besoin que le résultat soit aplati. SelectMany fait cela comme je l'ai découvert à partir de la réponse de Chris. –

Questions connexes