2009-04-05 5 views
2

Ich möchte die Ergebnisse einer Where-Klausel auf einer Liste und nehmen Sie dann diese Ergebnismenge und erstellen Sie nur einen neuen Typ, der alle seine Felder aus Aggregaten der ursprünglichen Abfrage erstellt hat . Gibt es also, wenn man das untenstehende grundlegende Beispiel anwendet, die beiden Linq-Anweisungen in einem zu kombinieren? Wenn das Original keine Zeilen enthält, sollte es null zurückgeben. Vielen Dank!Linq - Wie die Ergebnisse einer anderen Abfrage aggregieren

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 
     } 

Update: Für meine Situation hat der ursprüngliche Satz viele Elemente aber nach der where-Klausel ist die Ergebnismenge sehr klein. Das mehrmalige Aufzählen über den zweiten Satz sollte kein Problem darstellen. Auch muss ich zuerst und zuletzt auf dem Set verwenden, um einen Wert aus diesen Datensätzen zu erhalten. Die Gruppe nach Antwort funktioniert am besten für mich. Der aggregierte Weg ist sehr interessant und ich denke, dass er eine andere Verwendung dafür hat.

+0

Es ist relativ kompliziert, weil durch die Zeit, die Sie getestet haben, ob es ein Element ist, Du hast das erste Element verbraucht. Ich vermute, es gibt einen Weg dahin, aber es ist wahrscheinlich ein bisschen hacky ... Wird mehr denken. –

Antwort

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

dies funktioniert, aber seien Sie vorsichtig mit langen Listen, weil dies die gesamte Liste zweimal durchlaufen wird: g.Min() und g.Max(), und so wird die ursprüngliche Lösung. – Lucas

+0

... eigentlich 3 mal, zuerst GroupBy() – Lucas

9

Diese Lösung iteriert die Liste nur einmal mit Aggregate(), sondern auch für leere Listen wird es geben den Wert Samen. By the way, sind die Startwerte int.MaxValue und int.MinValue weil Math.Min(int.MaxValue, C) immer C zurückkehren und ebenfalls Math.Max(int.MinValue, C) immer C. Rückkehr

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) 
        }); 
Verwandte Themen