从DateTime列表中查找常见DateTime,如果没有常见,则查找最常见的

时间:2014-02-17 10:10:52

标签: c# asp.net-mvc algorithm linq

我想从我的数据库中DateTime的可用列表中找到常见的DateTime

背景

让我们假设,

我想见到一些人,我说我希望在Datetime X(2014-02-16 09:00:00.000)到DateTime Y(2014-02-26 05:00:00.000)之间遇到某些人。

然后我想见的人将回复说我将在以下日期提供:Date1(从某个开始时间到某个结束时间的某个日期),Date2(从某个时间到某个时间的特定日期),...等等。

让我们考虑这些是回应

Attendee1 (有些GuidId):

Response1:开始时间= 2014-02-23 09:00 AM,EndTime = 2014-02-17 11:00 AM,

Response2:开始时间= 2014-02-24 10:00 AM,结束时间= 2014-02-17 12:00 PM,

Response3:开始时间= 2014-02-25 10:00 AM,EndTime = 2014-02-17 11:00 AM,

Response4:开始时间= 2014-02-23 01:00 PM,EndTime = 2014-02-17 5:00 PM

Attendee2 (有些GuidId):

Response1:开始时间= 2014-02-22 09:00 AM,EndTime = 2014-02-17 05:00 PM,

Response2:开始时间= 2014-02-23 09:00 AM,EndTime = 2014-02-17 05:00 PM,

Response3:开始时间= 2014-02-25 09:00 AM,EndTime = 2014-02-17 12:00 PM,

Attendee3 (有些GuidId):

Response1:开始时间= 2014-02-22 11:00 AM,EndTime = 2014-02-17 02:00 PM,

Response2:开始时间= 2014-02-23 04:00 PM,EndTime = 2014-02-17 03:00 PM,

Response3:开始时间= 2014-02-23 04:00 PM,EndTime = 2014-02-17 05:00 PM,

Response4:开始时间= 2014-02-24 02:00 AM,EndTime = 2014-02-17 05:00 PM,

Response5:开始时间= 2014-02-25 11:00 AM,EndTime = 2014-02-17 12:00 PM,

此处,在上述场景中,系统应提供匹配日期:

2014-02-23 04:00 PM to 2014-02-23 05:00 PM 

2014-02-25 11:00 AM to 2014-02-25 12:00 PM

所以每一个人都回复了。我想找到共同的DateTime或共同List<DateTime>(如果存在)。

或者找到匹配次数最多的DateTime(List)

我知道我必须展示我所尝试过的以及我所做的事情,但我不知道我应该如何开始。

任何建议或提示都将不胜感激。

修改1

因此,在数据库中有一个名为Appointment的表,用于存储StartDateTimeEndDateTime

public class Appointment
{

    [Key]
    public Guid Id { get; set; }

    public virtual ICollection<Attendee> Attendees { get; set; }

    public DateTime StartDateTime { get; set; }
    public DateTime EndDateTime { get; set; }      

}

在这些日期之间,参加会议的人(参加者)将给予回复。 每个人(谁都会回复),他们的信息都存储在名为Attendees

的数据库表中
public class Attendee
{
    public Guid AttendeeId { get; set; }
    public virtual ICollection<Response> Responses { get; set; } 
}

对于每个用户,他们的响应存储在Responses表中,其模型看起来像

public class Response
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public Guid AttendeeId { get; set; }
    public DateTime StartDateTime { get; set; }
    public DateTime EndDateTime { get; set; }

}

PS : 它是MVC application,数据库是使用code first approach创建的。

另外,将AppointmentId添加到Response表是否有意义?或者那是不好的方法?但我认为这会使查询更容易。

1 个答案:

答案 0 :(得分:1)

可能有效的方法:

  • 计算每个人都可以参加的组合列表。
  • 您将从第一位参加者的所有回复开始,然后通过其他与会者进行枚举。
  • 在您列举的时候,对于每个仍然可以工作的潜在时间,缩短时间窗口以适应所有可能的与会者可以使用的所有时间

可能需要一些触摸来处理边缘情况,但以下代码应该让您走上正确的道路:

public class MeetingTime 
{
  DateTime Start { get; set; }
  DateTime End { get; set; }
  List<Response> Responses { get; set; }
  public int NumAttendees 
  {        
    get { return Responses.Select(x => x.AttendeeId).Distinct().Count(); }
  }

  public MeetingTime(Response response) 
  {
    Start = response.StartDateTime;
    End = response.EndDateTime;
    Responses = new List<Response>();
  }

  public void MergeMeetingTime(Response response) 
  {
    // if response times are within current times, can be merged
    if (Start <= response.StartDateTime && response.EndDateTime <= End)
    {
       Start = response.StartDateTime;
       End = response.EndDateTime;
       Responses.Add(response);
    }
  }
}

public List<MeetingTime> FindMeetingTimes() 
{
  var attendees = GetAttendees();
  var times = new List<MeetingTime> 
  bool isFirstAttendee = true;
  foreach (Attendee attendee in attendees) 
  {
    if (isFirstAttendee) 
    {
      foreach (Response response in attendee.Responses)
      {
        times.Add(new MeetingTime(response));
      }
      isFirstAttendee = false;
    } 
    else 
    {
      // Go through attendee.Responses and compare each with the current times
      // for each one, if it overlaps with a MeetingTime, then adjust 
      // the Start/End dates accordingly and increment Count
      // Uses same approach as above.          
      foreach (Response response in attendee.Responses)
      {
        times.ForEach(x => x.MergeMeetingTime(response));
      }
    }
  }
  // Remove all times where not everyone can attend
  times.Remove(x => x.NumAttendees < attendees.Count()).ToList();
  return times;
}

最后,您删除所有不是每个人都可以参加的时间。剩下的时间应该都包含所有参加者可以制作的开始/结束日期时间。