2009-05-14 5 views
4

Ok das ist irgendwie eine chaotische Abfrage und ich habe nur begrenzten Erfolg damit. Ich habe eine Liste einer Foo-Klasse, die eine Datetime-Eigenschaft und andere Daten hat. Ich habe eine Klasse/Zeile für fast jede Minute, mit einigen fehlenden und einige ganze Tage fehlen wie ein Urlaub oder ein Wochenende. Mein Ziel ist es, jeden Tag für alle Zeilen von einer Startzeit bis zu einer Endzeit zu gruppieren.Linq-Gruppe von einer Startzeit bis Endzeit auf DateTime Spalte

Also an einigen Tagen kann meine Startzeit 9:30 Uhr und Endzeit 3:00 Uhr sein. Diese Situation handle ich folgendermaßen:

DateTime sd = new DateTime(2000, 1, 1, 9, 30, 0); 
DateTime ed = new DateTime(2000, 1, 1, 15, 0, 0); 
var z = Foos.Where(a=> a.FooDate.TimeOfDay >= sd.TimeOfDay && 
    a.FooDate.TimeOfDay < ed.TimeOfDay) 
    .GroupBy(a=>a.FooDate.Date); 

Das funktioniert gut. Mein Problem ist manchmal eine Startzeit von 9 Uhr und eine Endzeit von 6 Uhr. In diesem Fall möchte ich, dass die Gruppe von Foos über Nacht geht, und wenn die 21 Uhr an einem Freitag ist und es bis zum nächsten Montag keine Zeilen gibt, möchte ich, dass die Gruppe das Wochenende überspannt. Ich wäre sogar glücklich mit einem Vorschlag einer Anfrage, die einfach immer zum nächsten Tag gehen würde.

Ich hoffe, dass das klar ist und alle Ideen zu schätzen wissen. Ich habe viele andere Möglichkeiten ausprobiert, dies mit Loops zu tun und eine andere Liste mit verschiedenen Daten und dergleichen zu erstellen, bin aber nicht damit zufrieden.

+0

Ich bin verwirrt, was Sie zu bestimmen versuchen. Versuchen Sie, die Zeit zwischen den Einträgen (Foos) zu erhalten? oder zählst du die Anzahl der Einträge zwischen zwei Zeiten? – Jeremy

+0

Ich versuche, die Liste der foo Objekte in einen Zeitbereich zu gruppieren. Also, am ersten Tag gibt es Daten, die von der Startzeit dieses Tages bis zum nächsten Tag gruppiert werden würden. Dann an diesem Tag wieder zur Startzeit starten und fortfahren. – RBear

Antwort

3
benutzte ich tun

In der Physik, wenn sie mit einem relativen Problem konfrontiert werden, wählen sie, wo Null ist. Wir auch.

// time range expressed as an example in "absolute" terms 
DateTime sd = new DateTime(2000, 1, 1, 9, 30, 0); 
DateTime ed = new DateTime(2000, 1, 2, 6, 0, 0); 

// time range expressed as a zero and range - "relative" terms 
TimeSpan zero = sd.TimeOfDay; 
TimeSpan range = ed.Subtract(sd); 

//the inputs 
List<DateTime> myList = new List<DateTime>() 
{ 
    new DateTime(2009, 1, 1, 10, 0, 0), //group1 
    new DateTime(2009, 1, 1, 17, 0, 0), //group1 
    new DateTime(2009, 1, 2, 9, 0, 0), //this is filtered 
    new DateTime(2009, 1, 2, 10, 0, 0), //group2 
    new DateTime(2009, 1, 2, 15, 0, 0), //group2 
    new DateTime(2009, 1, 3, 3, 0, 0), //group2 
    new DateTime(2009, 1, 3, 7, 0, 0), //this is filtered 
    new DateTime(2009, 1, 3, 10, 0, 0) //group3 
}; 

    //at last, the query. 
var query = myList 
    .Where(d => d.Subtract(zero).TimeOfDay < range) 
    .GroupBy(d => d.Subtract(zero).Date); 

// output the results 
foreach (var g in query) 
{ 
    Console.WriteLine("{0}", g.Count()); 
    foreach (var d in g) 
    { 
    Console.WriteLine(" {0}", d); 
    } 
} 

Ergebnisse:

2 
    1/1/2009 10:00:00 AM 
    1/1/2009 5:00:00 PM 
3 
    1/2/2009 10:00:00 AM 
    1/2/2009 3:00:00 PM 
    1/3/2009 3:00:00 AM 
1 
    1/3/2009 10:00:00 AM 
+0

WOW! Genau danach suche ich. Es wird auch in meinem regulären Fall funktionieren. Vielen Dank! – RBear

0

Dies funktioniert, aber es kann nicht als jeder schönere sein, was Sie bereits

private List<groupFoo> groupFoos(List<foo> foos) 
    { 

     //Group by Day into groupFoo 
     var z = foos.GroupBy(a => a.FooDate.ToShortDateString()).Select(x => new groupFoo() { Key = x.Key, Start = x.First().FooDate, End = x.Last().FooDate }).ToList(); 


     //Create new list to hold groups 
     var groupedFoos = new List<groupFoo>(); 

     //add all the good groups to the list 
     groupedFoos.AddRange(z.FindAll(zz => zz.Start.CompareTo(zz.End) != 0)); 

     //Remove all of the good groups from the orignal list 
     groupedFoos.ForEach(gf => z.RemoveAt(z.IndexOf(gf))); 

     //Sort whats left 
     z.Sort((a, b) => { return a.Start.CompareTo(b.Start); }); 

     while (z.Count > 1) 
     { 
      //grab the first 2 
      var y = z.Take(2); 

      //create a new group foo and add it to the good list 
      groupedFoos.Add(y.Aggregate((a, b) => new groupFoo() { Key = a.Key, Start = a.Start, End = b.End })); 

      //remove the bad ones 
      y.ToList().ForEach(yy => z.RemoveAt(z.IndexOf(yy))); 


     } 

     return groupedFoos; 
    } 

und groupFoo sieht aus wie dieses

public class groupFoo 
{ 

    public string Key { get; set; } 
    public DateTime Start { get; set; } 
    public DateTime End { get; set; } 

} 

die Probe

 List<foo> foos = new List<foo>(); 

     foos.Add(new foo() { FooDate = new DateTime(2009, 1, 1, 9, 0, 0) }); 
     foos.Add(new foo() { FooDate = new DateTime(2009, 1, 1, 17, 0, 0) }); 
     foos.Add(new foo() { FooDate = new DateTime(2009, 1, 2, 9, 30, 0) }); 
     foos.Add(new foo() { FooDate = new DateTime(2009, 1, 3, 6, 0, 0) }); 
     foos.Add(new foo() { FooDate = new DateTime(2009, 1, 4, 9, 0, 0) }); 
     foos.Add(new foo() { FooDate = new DateTime(2009, 1, 4, 21, 0, 0) });