2010-12-04 11 views
6

Si j'ai un IOrderedEnumberable<Car>, je le tri puis effectuez une requête de projection ...Dans LINQ, faire des projections sur un IOrderedEnumerable <T> préserver la commande?

est l'ordre conservé dans la projection?

Par exemple, ce scénario fonctionne-t-il?

IOrderedEnumberable<Car> allCarsOrderedFastestToSlowest = 
      GetAllCars() 
        .OrderByDescending(car=>car.TopSpeed); 

var top3FastestCarManufacturers = 
      allCarsOrderedFastestToSlowest 
        .Select(car=>car.Manufacturer) 
        .Distinct() 
        .Take(3); 

Est-ce que le nom de la variable top3FastestCarManufacturers véhiculent le sens de ce qui est vraiment arrivé dans le code?

+0

double possible de [Maintien de l'ordre avec LINQ] (http: //stackoverflow.com/questions/204505/preserving-order-with-linq) –

+0

D'accord avec la suggestion en double et cette question aurait reçu une réponse. Presque une sous-question spécifique de celui-là. Vous ne savez pas si vous souhaitez supprimer ou voter pour fermer en référence à l'autre question? –

Répondre

3

La documentation de la méthode Distinct ne dit rien quant à savoir si l'ordre est conservé ou non. C'est probablement parce que cela dépend de l'implémentation sous-jacente de la source.

Vous pouvez utiliser le regroupement pour obtenir le résultat souhaité, en obtenant la voiture la plus rapide de chaque fabricant, puis obtenir les trois plus rapides de ce:

var topThreeFastestCarManufacturers = 
    GetAllCars() 
    .GroupBy(c => c.Manufacturer) 
    .Select(g => g.OrderByDescending(c => c.TopSpeed).First()) 
    .OrderByDescending(c => c.TopSpeed) 
    .Take(3); 
+0

C'est un bon moyen de le faire si tout ce dont vous avez besoin est d'une colonne (propriété) de la table (objet), mais il se décomposera si vous en avez besoin de plus d'un - disons que vous voulez la marque et le modèle des voitures du "top 3" des fabricants. Pas vraiment une critique de la technique, mais elle repose sur le fait que vous n'avez pas à maintenir l'intégrité des tuples qui se décompose lorsque vous avez plus d'une propriété d'intérêt. – tvanfosson

+0

@tvanfosson: Que voulez-vous dire? Il renvoie trois objets de voiture complets avec toutes les propriétés, pas une seule propriété. Ironiquement, votre propre réponse * a * cette limitation ... – Guffa

+0

désolé, ne doit pas avoir lu assez attentivement. Je pensais que vous faisiez une requête qui se traduisait par 'select manufacturer, max (topspeed) de ...' Je me demande à quoi ressemble le SQL pour ça. – tvanfosson

3

Je soupçonne que ce qui va vous déranger est le Distinct. Cela réorganisera probablement les résultats par fabricant pour produire les résultats distincts. Je vais probablement parcourir la liste jusqu'à ce que j'ai trois fabricants distincts.

La sélection conserve l'ordre mais les remarques sur Distinct indiquent qu'elle renvoie un ensemble de résultats non ordonné et qu'il dépend de l'implémentation. Pour être sûr, je ne compterais pas sur le maintien de la commande et je le ferais simplement en utilisant l'itération.

var top3 = new List<string>(); 
foreach (var manufacturer in allCarsOrderedFastestToSlowest 
           .Select(car=>car.Manufacturer)) 
{ 
    if (!top3.Contains(manufacturer)) 
    { 
     top3.Add(manufacturer); 
     if (top3.Count == 3) 
     { 
      break; 
     } 
    } 
}