代码之家  ›  专栏  ›  技术社区  ›  leora Matt Lacey

正在寻找C#算法来从DateTime对象集合中获取重复项目(同时考虑日期和时间)?

  •  0
  • leora Matt Lacey  · 技术社区  · 11 年前

    我收集了 DateTime 物体。我需要从这个原始列表中“解析”出子集合,以获取基于重复的相关项目。所以我需要带上这一个原创系列:

    var collectionOfDateTime = GetDateTimeCollection();
    

    并将其转化为 日期时间 集合,其中每个集合包括第一个列表中遵循特定重复模式的一组日期。

    在下面的示例中,我不包括时间,但在实际需求中,这些项目同时包含Date和time元素。因此,例如,日期需要相隔7天,但也必须是同一时间(2月3日上午11点的一次与2月10日下午3点的一个时间不匹配,但与2月10am 11点的时间匹配)

    例如,假设我的重复模式是“每周”(在其他情况下可能是“每月”),我的日期集合如下所示:

     var date1 = DateTime.Today.AddHours(8);
     var date2 = DateTime.Today.AddWeeks(1).AddHours(8);
     var date3 = DateTime.Today.AddDays(3);
     var date4 = DateTime.Today.AddWeeks(8).AddHours(6);
    
     var collectionOfDateTime = new List<DateTime>() { date1, date2, date3, date4 };
    

    我想要一个函数(让我们调用它 StripOutSubCollections() )通过 collectionOfDateTime 以及它的“每周”和返回一个集合的事实,其中包括 date1 , date2 (因为它们都是同一周时段的一部分)。注意日期3不合适,日期4也不合适,因为时间与其他时间不匹配

    对于另一个帮助证明需求的例子,如果原始集合的输入是这样的:

     var date1 = DateTime.Today;
     var date2 = DateTime.Today.AddWeeks(1);
     var date3 = DateTime.Today.AddDays(3);
     var date4 = DateTime.Today.AddWeeks(8);
     var date5 = DateTime.Today.AddDays(3).AddWeeks(2);
    
     var collectionOfDateTime = new List<DateTime>() { date1, date2, date3, date4, date5 };
    

    我希望此函数返回2个列表(一个列表 日期1 , 日期2 date4 )和另一个列表 date3 date5 .

    如果我需要更多的例子来阐明需求,请告诉我?请注意,其中一个日期可能属于多个输出列表,这很好。

    我可以将每周转换为数字7,并对每个项目进行循环,从第一个项目开始到最后,然后从第二个项目到最后,再到第三个项目,等等。但我想看看是否有更优雅的方法

    3 回复  |  直到 11 年前
        1
  •  2
  •   JerKimball    11 年前

    如果我能正确理解你的问题,你就是在试图“拼凑” DateTime 按星期几计算的价值?

    如果是这样的话,应该这样做:

    var byDayOfWeek = collectionOfDateTime.GroupBy(dt => dt.DayOfWeek);
    // Optionally convert to a dictionary by day of week
    var asDict = byDayOfWeek.ToDictionary(grp => grp.Key, grp => grp.ToList());
    
    foreach(var kvp in asDict)
    {
        Console.WriteLine("Day:" + kvp.Key);
        foreach (var value in kvp.Value)
        {
            Console.WriteLine(value);
        }
    }
    

    输出:

    Day:Thursday
    2/21/2013 12:00:00 AM
    2/28/2013 12:00:00 AM
    4/18/2013 12:00:00 AM
    Day:Sunday
    2/24/2013 12:00:00 AM
    

    编辑:对于多个“分组依据”规则:

    public enum ChunkType
    {
        Weekly,
        Monthly,
        Yearly
    }
    
    public IEnumerable<IEnumerable<DateTime>> ChunkDates(IEnumerable<DateTime> collection, ChunkType chunkBy)
    {
        switch(chunkBy)
        {
            case ChunkType.Weekly:
                // roughly equals by day of week
                return collection.GroupBy(dt => dt.DayOfWeek).Select(grp => grp.ToList());
            case ChunkType.Monthly:
                // Trickier - assume by ordinal day of month?
                return collection.GroupBy(dt => dt.Day).Select(grp => grp.ToList());
            case ChunkType.Yearly:
                // Trickier - assume by ordinal day of year?
                return collection.GroupBy(dt => dt.DayOfYear).Select(grp => grp.ToList());        
        }
        return new[]{ collection };
    }
    
    var date1 = DateTime.Today;
    var date2 = DateTime.Today.AddDays(7);
    var date3 = DateTime.Today.AddDays(3);
    var date4 = DateTime.Today.AddDays(8*7);
    
    var collectionOfDateTime = new List<DateTime>() { date1, date2, date3, date4};
    
    foreach(var type in new [] { ChunkType.Weekly, ChunkType.Monthly, ChunkType.Yearly })
    {
        Console.WriteLine("Now grouping by:" + type);
        var grouped = ChunkDates(collectionOfDateTime, type);
        foreach(var groupOfDates in grouped)
        {
            Console.WriteLine("New group!");
            foreach (var value in groupOfDates)
            {
                Console.WriteLine(value);
            }
        }
    }
    

    输出:

    Now grouping by:Weekly
    New group!
    2/21/2013 12:00:00 AM
    2/28/2013 12:00:00 AM
    4/18/2013 12:00:00 AM
    New group!
    2/24/2013 12:00:00 AM
    
    Now grouping by:Monthly
    New group!
    2/21/2013 12:00:00 AM
    New group!
    2/28/2013 12:00:00 AM
    New group!
    2/24/2013 12:00:00 AM
    New group!
    4/18/2013 12:00:00 AM
    
    Now grouping by:Yearly
    New group!
    2/21/2013 12:00:00 AM
    New group!
    2/28/2013 12:00:00 AM
    New group!
    2/24/2013 12:00:00 AM
    New group!
    4/18/2013 12:00:00 AM
    
        2
  •  0
  •   Benny    11 年前
    var dict = new Dictionary<int, List<DateTime>>();
    foreach (var date in collectionOfDateTime) 
    {
      if (dict.Contains(date.DayOfWeek))
      {
         dict[date.DayOfWeek].Add(date);
      }
      else 
      {
         dict.Add(date.DayOfWeek, new List<Date> { date });
      }
    }
    
        3
  •  0
  •   rsenna    11 年前

    使用LINQ

    试试(类似于,这是LINQ风格的伪代码)

    var datecollections = from d in collectionOfDateTime
              group d by d.DayOfWeek into g
              select new { Day = g.Key, Date = g };
    

    试试看它会给你带来什么。。。