C # Linq or Lambda expression Group by week IEnumerable list with date field

I am trying to query IEnumerable<Object> to group by week, for example:

 Project(Name, DateStart,ID) 

I have an IEnumerable<Project> , and I want to make a report, grouping by week.

For exmaple:

 Week 1 Project1 8/4/2013 ID1 Project2 9/4/2013 ID2 Week 2 Project1 16/4/2013 ID3 Project2 18/4/2013 ID5 Week 3 Project1 24/4/2013 ID7 Project2 26/4/2013 ID8 

Please, if someone can give me a hand, I really appreciate that! I tried to make a lambda expression, but to no avail.

Thanks!

+4
source share
6 answers
 var weekGroups = projects .Select(p => new { Project = p, Year = p.DateStart.Year, Week = CultureInfo.InvariantCulture.Calendar.GetWeekOfYear (p.DateStart, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday) }) .GroupBy(x => new { x.Year, x.Week }) .Select((g, i) => new { WeekGroup = g, WeekNum = i + 1, Year = g.Key.Year, CalendarWeek = g.Key.Week }); foreach (var projGroup in weekGroups) { Console.WriteLine("Week " + projGroup.WeekNum); foreach(var proj in projGroup.WeekGroup) Console.WriteLine("{0} {1} {2}", proj.Project.Name, proj.Project.DateStart.ToString("d"), proj.Project.ID); } 
+13
source

You will need to define a function that can determine which week the date is:

 int GetWeek(DateTime date) { ... } 

Then LINQ query to the group:

 IEnumerable<IGrouping<int, Project>> groupedProjects = myListOfProjects.GroupBy(p => GetWeek(p.DateStart)); 

You can iterate over the list of grouped projects:

 foreach (var weekGroup in groupedProjects) { int week = weekGroup.Key; foreach (var project in weekGroup) { Console.WriteLine("Week " + week + " | Project: " + project.ID); } } 
+1
source

I think that to simplify this task, you can add the WeekNumber property to the Project class and populate it when you create the project object after you can easily group the WeekNumber property

 Project(Name, DateStart,ID,WeekNumber) 
0
source

You can use the added GetWeekOfMonth added here :

and then do something like:

  var groups = projects.GroupBy(p => p.Start.GetWeekOfMonth()); foreach (var group in groups) { Console.WriteLine("Week {0}", group.Key); foreach (var project in group) { Console.WriteLine("\t{0} | {1:dd/MM/yyyy} | {2}", project.Name, project.Start, project.Id); } } 
0
source

I think that just a simple projection will suffice:

 // we'll just use the existing settings on the box. DateTimeFormatInfo dfi = DateTimeFormatInfo.CurrentInfo; var cal = dfi.Calendar; var Projects = GetProjectsFromSomewhere(); // assuming IEnumerable<Project> int week = 1; // this *could* be changed and projected in the Select instead. foreach (var wg in from p in Projects group p by cal.GetWeekOfYear( p.StartDate, dfi.CalendarWeekRule, dfi.FirstDayOfWeek)) { Console.WriteLine("Week {0}", week); foreach (var p in wg) { Console.WriteLine(" {0} {1} {2}", p.Name, p.StartDate, p.ID); } week++; } 
0
source

In addition to Tim Schmelter's answer, you can get the date of the first day of the week, and then the group by that date.

Get the date of the first day of the week. you can use this code:

 public static class DateTimeExtensions { public static DateTime StartOfWeek(this DateTime dt, DayOfWeek startOfWeek) { int diff = dt.DayOfWeek - startOfWeek; if (diff < 0) { diff += 7; } return dt.AddDays(-1 * diff).Date; } } 

then you can group by the first date of the week as follows:

 var weekGroups = projects .Select(p => new { Project = p }) .GroupBy(x => x.Project.DateStart.StartOfWeek(DayOfWeek.Monday)) .Select((g, i) => new { WeekGroup = g, WeekNum = i + 1 }); foreach (var projGroup in weekGroups) { Console.WriteLine("Week " + projGroup.WeekNum); foreach(var proj in projGroup.WeekGroup) Console.WriteLine("{0} {1} {2}", proj.Project.Name, proj.Project.DateStart.ToString("d"), proj.Project.ID); } 
0
source

All Articles