2009-05-14 11 views
4

Ok, c'est un peu une requête désordonnée et je n'ai que peu de succès avec elle. J'ai une liste d'une classe Foo qui a une propriété datetime et d'autres données. J'ai une classe/rangée pour presque toutes les minutes, avec quelques manques et quelques jours entiers manquant comme des vacances ou un week-end. Mon objectif est de regrouper chaque jour pour toutes les lignes d'une heure de début à une heure de fin.groupe linq par une heure de début à la fin sur DateTime Colonne

Donc, certains jours, mon heure de début mai 9h30 et fin de 15h00. Cette situation que je gère par ce qui suit:

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); 

Cela fonctionne très bien. Mon problème est parfois que j'ai un début de 21 heures et une heure de fin de 6 heures du matin. Dans ce cas je veux que le groupe de foos passe la nuit, et si le 21h est un vendredi et qu'il n'y a pas de rang avant le lundi suivant je veux que le groupe couvre le week-end. Je serais même heureux avec une suggestion d'une requête qui irait toujours tout le jour suivant.

J'espère que c'est clair et apprécier toutes les idées. J'ai essayé beaucoup d'autres façons de le faire avec des boucles et de créer une autre liste de dates distinctes et autres, mais je ne suis pas content.

+0

Je suis confus quant à ce que vous essayez de déterminer. Essayez-vous d'obtenir la quantité de temps entre les entrées (Foos)? ou comptez-vous le nombre d'entrées entre deux fois? – Jeremy

+0

J'essaie de grouper la liste des objets foo dans une plage de temps. Donc, le premier jour, il y a des données qui seraient regroupées entre l'heure de début de la journée et le jour suivant, il y a la fin des données. Puis, ce jour-là, recommencez à l'heure de départ et continuez. – RBear

Répondre

3

En physique, confrontés à un problème relatif, ils peuvent choisir où est zéro. Nous aussi.

// 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); 
    } 
} 

Résultats:

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! C'est juste ce que je cherche. Cela fonctionnera aussi sur mon cas normal. Merci beaucoup! – RBear

0

Cela fonctionne, mais il ne peut pas être plus jolie que tout ce que vous faites déjà

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; 
    } 

et groupFoo ressemble à ce

public class groupFoo 
{ 

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

} 

l'échantillon je

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