2010-12-03 16 views
2

So schreiben Sie eine LINQ-Abfrage, die eine Zeile vom Typ "Value" mit Max. Datum und Max. Wert für dieses Datum zurückgibt. Es sollte die Zeile sein, in der Name = "Korrekt"Max. Wert aus Unterliste mit LINQ auswählen

Ich habe eine Abfrage am Ende geschrieben, und es funktioniert, nur versucht, einen richtigen Weg zu finden, dies zu tun.

Vielen Dank im Voraus

public class MeasurePoint 
{ 
    public int No { get; set; } 
    public string Weight { get; set; } 
    public List<Values> Vals { get; set; } 
} 

public class Values 
{ 
    public string Name { get; set; } 
    public int Val { get; set; } 
    public DateTime Date { get; set; } 
} 

public static class Test 
{ 
    public static void Calc() 
    { 
     var mps = new List<MeasurePoint>(); 

     mps.Add(new MeasurePoint() 
     { 
      No = 1, 
      Vals = new List<Values>() 
      { 
       new Values(){Date = DateTime.Now.Date.AddDays(1), Name = "testas", Val = 1}, 
       new Values(){Date = DateTime.Now.Date.AddDays(2), Name = "testas", Val = 5}, 
       new Values(){Date = DateTime.Now.Date, Name = "testas", Val = 15} 
      }}); 
     mps.Add(new MeasurePoint() 
     { 
      No = 2, 
      Vals = new List<Values>() 
      { 
       new Values(){Date = DateTime.Now.Date, Name = "testas", Val = 11}, 
       new Values(){Date = DateTime.Now.Date.AddDays(2), Name = "Correct", Val = 55}, 
       new Values(){Date = DateTime.Now.Date, Name = "testas", Val = 15} 
      } 
     }); 
     mps.Add(new MeasurePoint() 
     { 
      No = 3, 
      Vals = new List<Values>() 
      { 
       new Values(){Date = DateTime.Now.Date.AddDays(1), Name = "testas", Val = 111}, 
       new Values(){Date = DateTime.Now.Date.AddDays(2), Name = "testas", Val = 52}, 
       new Values(){Date = DateTime.Now.Date, Name = "testas", Val = 15} 
      } 
     }); 

     mps.Add(new MeasurePoint() 
     { 
      No = 4, 
      Vals = new List<Values>()      
     }); 

     var x = mps.ElementAt(0).Vals.Union(mps.ElementAt(1).Vals).Union(mps.ElementAt(2).Vals); 
     var z = x.Where(p => p.Date == x.Max(d => d.Date)).MaxBy(t=>t.Val); 

     //One more way I've found 
     var ttt = mps.SelectMany(p => p.Vals).GroupBy(t=>t.Date).MaxBy(r=>r.Key).MaxBy(g=>g.Val); 
    } 

Antwort

5
var max = mps.SelectMany(x => x.Vals) 
    .Aggregate((a, x) => (x.Date > a.Date) || 
         ((x.Date == a.Date) && (x.Val > a.Val)) ? x : a); 
+0

:) Cool :) Jetzt Idee, wie das funktioniert, aber es tut :) – Marty

+0

@Martynas: 'SelectMany' einfach" flacht "Ihre ursprüngliche Sammlung in eine einzige Sequenz mit allen' Values' Objekte aus den 'Vals' Sammlungen von alle 'MeasurePoint'-Objekte. 'Aggregat' schreitet dann durch die abgeflachte Sequenz und vergleicht jedes Element mit dem Maximum (bisher). Wenn das aktuelle Element größer als das Maximum ist, wird das zum neuen Maximum. Sobald alle Elemente verarbeitet wurden, wird das Maximum zurückgegeben. – LukeH

2

dieses

var result = mps.Where(m => m.Vals.Count > 0) 
    .SelectMany(m => m.Vals 
     .OrderByDescending(v => v.Date) 
     .Take(1), (m, v) => new {m.No, v.Date, v.Name, v.Val}); 

EDIT versuchen - das ist eine neue Version als Ausgabe

var result = mps.Where(m => m.Vals.Count > 0) 
    .SelectMany(m => m.Vals) 
    .OrderByDescending(v => v.Date) 
    .ThenByDescending(v => v.Val).Take(1); 
+0

Bin, das wäre korrekt, wenn ich nach Max Datum suchen müsste, aber es muss auch ein maximales "Val" für dieses Datum finden. Aber deine Idee ist nett :) danke – Marty

+0

Ich verstehe deine Anforderung jetzt - siehe zu meiner Antwort bearbeiten –

+0

Cool :) Werde alle von ihnen versuchen, um zu sehen, welche die beste Leistung geben :) – Marty

0

Wie kann mehr deutlich geworden ist, Verwenden Sie Anruf MaxBy(), wenn es eine Methode von IObservable<T> ist, während GroupBy()IEnumerable<T> zurückgibt?

+0

Heh :) Ich habe Reactive Linq Extensions installiert und total vergessen :) – Marty

+0

@Martynas: Bitte erwähnen Sie das in Ihrem Beitrag, um es klarer zu machen :) – abatishchev