views:

56

answers:

3

I have a serial of object defined as:

public class Foo
{
           public DateTime Time {get;set;}
}

now I want to group objects(IEnumerable<Foo>) according to the time, e.g. I want to group them according to hour or day or month.

for example (group into hour):

group 1(13:00-14:00) : foo1, foo2, foo3
group 2(14:00-15:00): foo4, foo5

How to write LINQ over this? hope I made myself clear.

+2  A: 

Hour is a property of DateTime, so it should be as simple as:

fooList.GroupBy(f => f.Hour)

That would give you an IGrouping<int, Foo> object, in which the int key is the hour.

Evgeny
+1  A: 

Here's an example using query expression.

public class Foo
{
    public int FooID { get; set; }
    public DateTime FooDate { get; set; }
}

...

List<Foo> foos = new List<Foo>()
{
    new Foo() { FooID = 1, FooDate = new DateTime(2010,3,15,18,30,0)},
    new Foo() { FooID = 2, FooDate = new DateTime(2010,3,15,19,30,0)},
    new Foo() { FooID = 3, FooDate = new DateTime(2010,3,15,20,30,0)},
    new Foo() { FooID = 4, FooDate = new DateTime(2010,3,15,18,15,0)},
    new Foo() { FooID = 5, FooDate = new DateTime(2010,3,15,18,45,0)},
    new Foo() { FooID = 6, FooDate = new DateTime(2010,3,15,20,15,0)},
    new Foo() { FooID = 7, FooDate = new DateTime(2010,3,15,19,15,0)}
};

var query = from foo in foos
            group foo by foo.FooDate.Hour
                into foogroup
                select new
                {
                    Hour = foogroup.Key,
                    Foos = foos.Where(foo => foo.FooDate.Hour == foogroup.Key)
                };

foreach (var group in query)
{
    Console.WriteLine(group.Hour);
    foreach (Foo foo in group.Foos)
        Console.WriteLine("\t{0}\t{1}", foo.FooID, foo.FooDate);
}

Edit: Regarding the need to seperate days, months, etc., you can extend your grouping like the following

var query = from foo in foos
            group foo by new { Date = foo.FooDate.Date, Hour = foo.FooDate.Hour }
                into foogroup
                select new
                {
                    Date = foogroup.Key.Date,
                    Hour = foogroup.Key.Hour,
                    Foos = foos.Where(foo => 
                        foo.FooDate.Date == foogroup.Key.Date 
                        && foo.FooDate.Hour == foogroup.Key.Hour)
                };
Anthony Pegram
+1  A: 

If you don't want to group the 13-14hr yesterday with the 13-14hr today, nor the 5th of this month with the 5th of last month etc. so you'll need to do something like:-

// splitting time up into hour intervals
fooList.GroupBy(f => f.Time.Date.AddHours(f.Time.Hour))

// splitting time up into day intervals
fooList.GroupBy(f => f.Time.Date)

// splitting time up into month intervals
fooList.GroupBy(f => f.Time.Date.AddDays(-f.Time.Day))

If you really do want to map all of the same hour/day/month into the same group then it's easier.

Hightechrider
exactly what i want. thanks.
Benny