C# 累积日期范围

C# 累积日期范围,c#,datetime,C#,Datetime,我收到一个日期范围列表作为输入。有些是重叠的,有些是相邻的。是否存在累积传入日期范围的集合 例如: (2018/01/01, 2018/01/02), (2018/02/15, 2018/03/21), (2018/01/10, 2018/01/10), (2018/01/03, 2018/01/09) 结果: (2018/01/01, 2018/01/10), // 1st, 3rd, 4th lines combined (2018/02/15, 2018/03/21) // 2nd

我收到一个日期范围列表作为输入。有些是重叠的,有些是相邻的。是否存在累积传入日期范围的集合

例如:

(2018/01/01, 2018/01/02),
(2018/02/15, 2018/03/21),
(2018/01/10, 2018/01/10), 
(2018/01/03, 2018/01/09)
结果:

(2018/01/01, 2018/01/10), // 1st, 3rd, 4th lines combined
(2018/02/15, 2018/03/21)  // 2nd line

我认为c#中没有一个函数或容器可以自动为您实现这一点,但当然您可以扩展某种集合来实现这一点。例如,以一个简单的列表为例,只覆盖Add()方法,以将现有项扩展一个范围,而不是添加一个新项(如果您希望累积日期范围的规则适用)

否标准库中没有此类集合。但是,您可以为它实现一个自定义的简单方法;假设句点为元组:


不,您必须自己这样做:(可能有助于处理样板循环代码,但如何(或是否)合并是您需要实现的。此日期来源于
2018/02/21
它不在输入中?非常好的解决方案Dmitry!非常感谢。
private static IEnumerable<Tuple<DateTime, DateTime>> Accumulate(
  IEnumerable<Tuple<DateTime, DateTime>> source) {

  var data = source
    .OrderBy(date => date.Item1)
    .ThenByDescending(date => date.Item2);

  DateTime left = DateTime.MinValue;  // make compiler be happy: initialization
  DateTime right = DateTime.MinValue; // -/-

  bool first = true;

  foreach (var item in data) {
    if (first) {
      left = item.Item1;
      right = item.Item2;

      first = false;
    }
    else if (right.AddDays(1) >= item.Item1) // can be combined; keep on combining
      right = item.Item2 > right ? item.Item2 : right;
    else {
      // can't be combined: return previous chunk
      yield return Tuple.Create(left, right);

      // start a new chunk
      left = item.Item1;
      right = item.Item2;
    }
  }

  // if we have a very last chunk to return, do it
  if (!first)
    yield return Tuple.Create(left, right);
}
  Tuple<DateTime, DateTime>[] test = new Tuple<DateTime, DateTime>[] {
    Tuple.Create(new DateTime(2018, 01, 01), new DateTime(2018, 01, 02)),

    Tuple.Create(new DateTime(2018, 02, 15), new DateTime(2018, 03, 21)),
    Tuple.Create(new DateTime(2018, 01, 10), new DateTime(2018, 01, 10)),
    Tuple.Create(new DateTime(2018, 01, 03), new DateTime(2018, 01, 09)),
  };

  var result = Accumulate(test)
    .ToList();

  string report = string.Join("," + Environment.NewLine, result
    .Select(item => $"({item.Item1:yyyy'/'MM'/'dd}, {item.Item2:yyyy'/'MM'/'dd})"));

  Console.Write(report);
(2018/01/01, 2018/01/10),
(2018/02/15, 2018/03/21)