2009-04-05 9 views
2

Je souhaite prendre les résultats d'une clause where dans une liste, puis prendre ce jeu de résultats et créer un seul nouveau type dont tous les champs sont construits à partir d'agrégats de la requête d'origine . Donc, étant donné l'exemple de base ci-dessous, y a-t-il moyen de combiner les deux instructions linq en une seule? Si l'original n'a pas de ligne, il doit retourner null. Merci!Linq - Comment agréger les résultats d'une autre requête

class Foo 
    { 
     public int A { get; set; } 
     public int B { get; set; } 
    } 
    List<Foo> lst = GetFooList(); 

     var q = (from f in lst 
       where f.A > 3 
       select f).ToList(); 
     if (q.Count != 0) 
     { 
      var qq = new 
      { 
       MinA = q.Min(l => l.A), 
       MaxB = q.Max(h => h.B), 
      }; 
      // now do something with qq 
     } 

Mise à jour: Pour ma situation, l'ensemble d'origine a beaucoup d'éléments, mais après la clause where le jeu de résultats est très faible. Énumérer plusieurs fois le second ensemble ne devrait pas poser de problème. Aussi, je dois utiliser le premier et le dernier sur l'ensemble pour obtenir une valeur de ces enregistrements. Le groupe par réponse fonctionnera le mieux pour moi. La manière globale est très intéressante et je pense avoir un autre usage pour cela.

+0

Il est, parce que relativement délicate au moment où vous avez testé si oui ou non il y a un élément , vous avez consommé ce premier élément. Je soupçonne qu'il y a un moyen de le contourner, mais ça risque d'être un peu hacker ... J'y penserai plus. –

Répondre

2
(from f in GetFooList() 
    where f.A > 3 
    group f by 1 into g 
    let MinA=g.Min(l=>l.A) 
    let MaxB=g.Max(h=>h.B) 
    select new {MinA, MaxB}).SingleOrDefault() 
+1

cela fonctionne, mais faites attention aux longues listes car cela va parcourir deux fois la liste entière: g.Min() et g.Max(), et la solution d'origine aussi. – Lucas

+0

... en réalité 3 fois, le premier étant GroupBy() – Lucas

9

Cette solution itère la liste une seule fois avec Aggregate(), mais pour les listes vides, il retournera la valeur de départ. Soit dit en passant, les valeurs de semences sont int.MaxValue et int.MinValue parce Math.Min(int.MaxValue, C) toujours revenir C et même Math.Max(int.MinValue, C) retourneront toujours C.

var b = lst.Where(f => f.A > 3) 
      .Aggregate(
        // seed, initial values 
        new 
        { 
        MinA = int.MaxValue, 
        MaxB = int.MinValue 
        }, 

        // accumulator function 
        (a,f) => new 
        { 
        MinA = Math.Min(a.MinA , f.A), 
        MaxB = Math.Max(a.MaxB , f.B) 
        }); 
Questions connexes