计算日期时间列表中的总分钟数

时间:2018-07-11 13:27:36

标签: c# algorithm

我有约会班的清单。 在下面的代码中;

  • 约会1,约会2和约会3相交。
  • 约会4和约会5相交。
  • 约会6不相交
  • 约会1,约会2和约会3开始日期时间为'2018-07-10 08:00:00',结束日期时间为'2018-07-10 12:00:00'< / strong>,这里的总时间为4个小时。
  • 约会4和约会5的开始日期时间为'2018-07-10 14:00:00',结束日期时间为'2018-07-10 17:00:00'这里的总时间是3个小时。
  • 约会6不相交来到这里1小时。

总时间是4 + 3 + 1 = 8,

如何在给定的约会日期时间值中找到8。

    class Program
    {
        static void Main(string[] args)
        {
            List<Appointment> appointments = new List<Appointment>();

            Appointment appointment1 = new Appointment();
            appointment1.StartDate = new DateTime(2018, 07, 11, 08, 00, 00);
            appointment1.FinishDate = new DateTime(2018, 07, 11, 11, 00, 00);

            Appointment appointment2 = new Appointment();
            appointment2.StartDate = new DateTime(2018, 07, 11, 10, 00, 00);
            appointment2.FinishDate = new DateTime(2018, 07, 11, 12, 00, 00);

            Appointment appointment3 = new Appointment();
            appointment3.StartDate = new DateTime(2018, 07, 11, 09, 00, 00);
            appointment3.FinishDate = new DateTime(2018, 07, 11, 12, 00, 00);

            Appointment appointment4 = new Appointment();
            appointment4.StartDate = new DateTime(2018, 07, 11, 14, 00, 00);
            appointment4.FinishDate = new DateTime(2018, 07, 11, 16, 00, 00);

            Appointment appointment5 = new Appointment();
            appointment5.StartDate = new DateTime(2018, 07, 11, 15, 00, 00);
            appointment5.FinishDate = new DateTime(2018, 07, 11, 17, 00, 00);

            Appointment appointment6 = new Appointment();
            appointment6.StartDate = new DateTime(2018, 07, 11, 18, 00, 00);
            appointment6.FinishDate = new DateTime(2018, 07, 11, 19, 00, 00);

            appointments.Add(appointment1);
            appointments.Add(appointment2);
            appointments.Add(appointment3);
            appointments.Add(appointment4);
            appointments.Add(appointment5);
            appointments.Add(appointment6);

            Console.ReadLine();
        }
    }
    public class Appointment
    {
        public DateTime StartDate { get; set; }
        public DateTime FinishDate { get; set; }
    }

4 个答案:

答案 0 :(得分:2)

让我们先排序约会,然后Aggregate:我们只有 3 个选项可以实现:

  1. 约会不相交
  2. 约会包括下一个约会
  3. 约会重叠

示例代码:

  var total = appointments
    .OrderBy(appointment => appointment.StartDate)
    .Aggregate(new Tuple<double, DateTime?>(0.0, null), (acc, item) => {
      if (!acc.Item2.HasValue || acc.Item2.Value <= item.StartDate) // Disjoint
        return new Tuple<double, DateTime?>(
          acc.Item1 + (item.FinishDate - item.StartDate).TotalHours, 
          item.FinishDate);
      else if (acc.Item2.Value >= item.FinishDate) // Include
        return acc;
      else // Partially overlap
        return new Tuple<double, DateTime?>(
          acc.Item1 + (item.FinishDate - acc.Item2.Value).TotalHours,
          item.FinishDate);
    })
    .Item1;

 // 8
 Console.WriteLine(total);

答案 1 :(得分:1)

您首先需要合并重叠的时间,然后对时间跨度求和:

void Main()
{
List<Appointment> appointments = new List<Appointment>();

            Appointment appointment1 = new Appointment();
            appointment1.StartDate = new DateTime(2018, 07, 11, 08, 00, 00);
            appointment1.FinishDate = new DateTime(2018, 07, 11, 11, 00, 00);

    Appointment appointment2 = new Appointment();
    appointment2.StartDate = new DateTime(2018, 07, 11, 10, 00, 00);
    appointment2.FinishDate = new DateTime(2018, 07, 11, 12, 00, 00);

    Appointment appointment3 = new Appointment();
    appointment3.StartDate = new DateTime(2018, 07, 11, 09, 00, 00);
    appointment3.FinishDate = new DateTime(2018, 07, 11, 12, 00, 00);

    Appointment appointment4 = new Appointment();
    appointment4.StartDate = new DateTime(2018, 07, 11, 14, 00, 00);
    appointment4.FinishDate = new DateTime(2018, 07, 11, 16, 00, 00);

    Appointment appointment5 = new Appointment();
    appointment5.StartDate = new DateTime(2018, 07, 11, 15, 00, 00);
    appointment5.FinishDate = new DateTime(2018, 07, 11, 17, 00, 00);

    Appointment appointment6 = new Appointment();
    appointment6.StartDate = new DateTime(2018, 07, 11, 18, 00, 00);
    appointment6.FinishDate = new DateTime(2018, 07, 11, 19, 00, 00);

    appointments.Add(appointment1);
    appointments.Add(appointment2);
    appointments.Add(appointment3);
    appointments.Add(appointment4);
    appointments.Add(appointment5);
    appointments.Add(appointment6);

    var ranges = appointments.Select(a => new Range {Start=a.StartDate, End=a.FinishDate});
    var total = MergeTimes(ranges).Sum(a => (a.End-a.Start).TotalHours);
    Console.WriteLine(total);
}

public class Appointment
{
    public DateTime StartDate { get; set; }
    public DateTime FinishDate { get; set; }

}

public class Range
{
    public DateTime Start {get;set;}
    public DateTime End {get;set;}
}

public IEnumerable<Range> MergeTimes(IEnumerable<Range> times)
{
    if (times.Count() == 0)
    {
        return times;
    }
    Range[] orderedTimes = (from t in times
                            orderby t.Start
                            select t).ToArray();
    List<Range> merged = new List<Range>();
    Range current = new Range
    {
        Start = orderedTimes[0].Start,
        End = orderedTimes[0].End
    };
    for (int i = 0; i < orderedTimes.Length; i++)
    {
        if (current.Start <= orderedTimes[i].End && current.End >= orderedTimes[i].Start)
        {
            current.Start = ((current.Start < orderedTimes[i].Start) ? current.Start : orderedTimes[i].Start);
            current.End = ((current.End > orderedTimes[i].End) ? current.End : orderedTimes[i].End);
        }
        else
        {
            merged.Add(new Range
            {
                Start = current.Start,
                End = current.End
            });
            current = new Range
            {
                Start = orderedTimes[i].Start,
                End = orderedTimes[i].End
            };
        }
    }
    merged.Add(new Range
    {
        Start = current.Start,
        End = current.End
    });
    return merged;
}

答案 2 :(得分:0)

您知道TimeSpan类的属性吗?

(dateA - dateB).TotalMinutes

https://msdn.microsoft.com/en-us/library/system.timespan.totalminutes.aspx

答案 3 :(得分:0)

解决此问题的一种方法是收集约会所涉及的小时数,然后将其分组。

您可以在Appointment类中添加一个方法来获取约会所涉及的时间:

public IEnumerable<int> GetHours()
{
    List<int> hours = new List<int>();
    var startDate = StartDate;
    var finishDate = FinishDate;
    while(startDate < finishDate)
    {
        hours.Add(startDate.Hour);
        startDate = startDate.AddHours(1);
    }
    return hours;
}

然后可以将它们分组:

var result = appointments.SelectMany(a => a.GetHours()).GroupBy(i => i);

Console.WriteLine("Total hours: {0}", result.Count()); //This is the count
foreach (var hour in result)
{
    Console.WriteLine("{0} => {1}", hour.Key, hour.Count());
}

控制台中的输出:

Total hours: 8
8 => 1
9 => 2
10 => 3
11 => 2
14 => 1
15 => 2
16 => 1
18 => 1