【问题标题】:C# Linq or Lambda expression Group by Week IEnumerable list with date fieldC# Linq 或 Lambda 表达式 Group by Week IEnumerable 列表与日期字段
【发布时间】:2013-04-10 13:42:31
【问题描述】:

我正在尝试对 IEnumerable<Object> 进行查询以按周分组,例如:

Project(Name, DateStart,ID)

我有IEnumerable<Project>,我想做一个报告,按周分组。

例如:

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

如果有人可以帮我一把,我真的很感激!我试图做一个 lambda 表达式,但没有成功。

谢谢!

【问题讨论】:

  • 什么样的IEnumerable?什么 linq 提供程序(例如 Linq-To-SQL、Linq-To-Objects)?
  • Linq-to-Objects。我从我的模型中创建了一个 IEnumerable 类型的实体。
  • 请考虑接受对您有帮助的答案。

标签: c# linq lambda


【解决方案1】:
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);
}

【讨论】:

  • 这真是个天才,这个逻辑对我也很有效。我有一个人为此工作了好几个小时..
  • +1 甚至推荐这个提问者 (stackoverflow.com/questions/20689149/…) 来查看这个解决方案。看起来不错
  • 谢谢。 +1 这是一个非常容易理解的工作示例,使用 Linq 进行相当复杂的分组。会回来再看一遍,一遍又一遍,直到它烧到我的脑海里。
【解决方案2】:

您需要定义一个函数来确定日期在哪一周:

int GetWeek(DateTime date) { ... }

那么要分组的 LINQ 查询是:

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

您可以遍历分组的项目列表:

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

【讨论】:

  • 我可以在那里调用一个函数吗?
  • 在哪里?你的意思是IGrouping&lt;int, Project&gt;
  • 您可以按Calendar.GetWeekOfYear 进行分组,然后在第二步或迭代时“重命名”这些组。
【解决方案3】:

我认为为了简化此任务,您可以将 WeekNumber 属性添加到 Project 类中 并在创建 Project 对象时填写它,然后您可以轻松按 WeekNumber 属性进行分组

Project(Name, DateStart,ID,WeekNumber)

【讨论】:

  • 我不想要一年中的周顺序,只是组都属于一周......如果你明白我的意思......
【解决方案4】:

我认为只需一个简单的投影就足够了:

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

【讨论】:

    【解决方案5】:

    您可以使用GetWeekOfMonth 发布的扩展名here

    然后执行以下操作:

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

    【讨论】:

      【解决方案6】:

      除了 Tim Schmelter's 回答之外,您还可以获取一周中第一天的日期,然后按该日期分组。

      获取一周中第一天的日期。 您可以使用此代码:

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

      然后你可以像这样按一周的第一个日期分组:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-10-17
        • 2023-02-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多