LINQ to group objects according to timestamp
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):
g开发者_如何转开发roup 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.
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.
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)
};
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.
精彩评论