2015-01-25 3 views
1

Что я пытаюсь сделать, если вы посмотрите ниже в коде, напишите оператор Linq, который вернет группу ShiftEvents. Группа определена как 1.) EmpId, 2.) EndDate/Time одного ShiftEvent = StartDate/Time следующего ShiftEventИспользование Linq для поиска группы общих объектов

Я хочу, чтобы затем создать объект Shift, где я поместил группу ShiftEvents в Shift.List <ShiftEvents>.

У меня есть полузасутое письменное заявление Linq, похоже, похоже на ShiftEvents .. это часть группировки, в которой я полностью потерян.

class ShiftEvent{ 
    public int EmpId { get; set; } 
    public string Activity { get; set; } 
    public string StartDate { get; set; } 
    public string StartTime { get; set; } 
    public string EndDate { get; set; } 
    public string EndTime { get; set; } 
} 

class Shift{ 
    public List<ShiftEvent> ShiftEvents { get; set; } 
    public int EmployeeId { get; set; } 
    public DateTime StartOfShiftDate { get; set; } 
    public DateTime StartOfShiftTime { get; set; } 
    public DateTime EndOfShiftDate { get; set; } 
    public DateTime EndOfShiftTime { get; set; } 
} 

void Main() 
{ 
    List<ShiftEvent> se = new List<ShiftEvent>(); 
    // Group 1 
    se.Add(new ShiftEvent {EmpId=1, Activity="Test", StartDate="2015/01/21", StartTime="23:00",EndDate="2015/01/21",EndTime="23:30"}); 
    se.Add(new ShiftEvent {EmpId=1, Activity="Test", StartDate="2015/01/21", StartTime="23:30",EndDate="2015/01/22",EndTime="00:30"}); 
    se.Add(new ShiftEvent {EmpId=1, Activity="Test", StartDate="2015/01/22", StartTime="00:30",EndDate="2015/01/22",EndTime="05:30"}); 
    se.Add(new ShiftEvent {EmpId=1, Activity="Test", StartDate="2015/01/22", StartTime="05:30",EndDate="2015/01/22",EndTime="06:30"}); 
    se.Add(new ShiftEvent {EmpId=1, Activity="Test", StartDate="2015/01/22", StartTime="06:30",EndDate="2015/01/22",EndTime="07:00"}); 
    // Group 2 
    se.Add(new ShiftEvent {EmpId=1, Activity="Test", StartDate="2015/01/22", StartTime="07:15",EndDate="2015/01/22",EndTime="09:00"}); 
    se.Add(new ShiftEvent {EmpId=1, Activity="Test", StartDate="2015/01/22", StartTime="09:00",EndDate="2015/01/22",EndTime="10:00"}); 
    se.Add(new ShiftEvent {EmpId=1, Activity="Test", StartDate="2015/01/22", StartTime="10:00",EndDate="2015/01/22",EndTime="11:00"}); 
    se.Add(new ShiftEvent {EmpId=1, Activity="Test", StartDate="2015/01/22", StartTime="11:00",EndDate="2015/01/22",EndTime="12:00"}); 
    se.Add(new ShiftEvent {EmpId=1, Activity="Test", StartDate="2015/01/22", StartTime="12:00",EndDate="2015/01/22",EndTime="13:00"}); 
    // Group 3 
    se.Add(new ShiftEvent {EmpId=2, Activity="Test", StartDate="2015/01/22", StartTime="07:15",EndDate="2015/01/22",EndTime="09:00"}); 
    se.Add(new ShiftEvent {EmpId=2, Activity="Test", StartDate="2015/01/22", StartTime="09:00",EndDate="2015/01/22",EndTime="10:00"}); 
    se.Add(new ShiftEvent {EmpId=2, Activity="Test", StartDate="2015/01/22", StartTime="10:00",EndDate="2015/01/22",EndTime="11:00"}); 
    se.Add(new ShiftEvent {EmpId=2, Activity="Test", StartDate="2015/01/22", StartTime="11:00",EndDate="2015/01/22",EndTime="12:00"}); 
    se.Add(new ShiftEvent {EmpId=2, Activity="Test", StartDate="2015/01/22", StartTime="12:00",EndDate="2015/01/22",EndTime="13:00"}); 


    var obj = from s1 in se 
      join s2 in se 
       on new {EmpId = s1.EmpId, Date = s1.EndDate, Time = s1.EndTime} equals new {EmpId = s2.EmpId, Date=s2.StartDate, Time = s2.StartTime} 
      select s1; 

    var shiftList = new List<Shift>(); 

    foreach(var shiftEvent in obj){ 
     var shift = new Shift(); 
     shift.ShiftEvent.Add(shiftEvent); 
     shift.EmployeeId = shiftEvent.EmpId; 
     ....... 
     shiftList.Add(shift); 
    } 


} 

Любые указатели были бы замечательными!

+1

Итак, какая реальная проблема .. вы не заявили в своем решении 'half assed', почти работает или вообще не работает. – MethodMan

+0

Проблема в том, что я понятия не имею, с чего начать в моем заявлении Linq чтобы получить группу ShiftEvents. В примере кода есть 3 группы. Я не знаю, как сломать это из того, что у меня есть сейчас. – kirkdmo

+0

Код, который у вас есть, приведет к объединению записей внутри группы, но, кроме того, это не поможет. Например, для вашей группы №1 я ожидаю, что вы по-прежнему закончите работу с четырьмя записями (т. Е. Все, кроме последнего, у которого нет записи для соединения). Вы даже не принимаете значения с 's2', поэтому вы просто завершаете копией' s1'. Вместо этого мне кажется, что вы должны забыть «join», а вместо этого «group by» на сотруднике #, 'order by 'дату/время, а затем вне выражения LINQ, используйте, например. 'Aggregate()' для накопления смежных записей в отдельные объекты списка. –

ответ

2

Вы можете начать группируя сдвиг событие сотрудников:

var employeeShifts = _shiftEvents.GroupBy(item => item.EmpId); 

Тогда итерация на них, чтобы создать сдвиги. Создайте первую смену с событием первой смены. Если следующее событие смещения начинается, когда последний закончен, обновите дату окончания сдвига. Если есть пробел, добавьте сдвиг в список и начните новый сдвиг с текущего.

Вот и все. Это немного запуталось, потому что вы сохраняете информацию о времени как строку.

var employeeShifts = _shiftEvents.GroupBy(item => item.EmpId); 

List<Shift> shifts = new List<Shift>(); 
foreach (IGrouping<int, ShiftEvent> employeeShift in employeeShifts) 
{ 
    var orderedShiftEvents = employeeShift.Select(item => new { ShiftEvent = item, Interval = item.GetShiftInterval() }) 
              .OrderBy(item => item.Interval.Item1); 

    Shift currentShift = null; 
    foreach (var shiftEvent in orderedShiftEvents) 
    { 
     if (currentShift == null) 
     { 
      currentShift = shiftEvent.ShiftEvent.StartShift(shiftEvent.Interval); 
      continue; 
     } 

     if (currentShift.EndOfShiftDate == shiftEvent.Interval.Item1) 
     { 
      currentShift.EndOfShiftDate = shiftEvent.Interval.Item2; 
      currentShift.ShiftEvents.Add(shiftEvent.ShiftEvent); 
     } 
     else 
     { 
      shifts.Add(currentShift); 
      currentShift = shiftEvent.ShiftEvent.StartShift(shiftEvent.Interval); 
     } 
    } 
    shifts.Add(currentShift); 
} 

Методы расширения, я должен был использовать:

public static class ShiftEventExtensions 
{ 
    public static Tuple<DateTime, DateTime> GetShiftInterval(this ShiftEvent shiftEvent) 
    { 
     return new Tuple<DateTime, DateTime>(ParseDateTime(shiftEvent.StartDate, shiftEvent.StartTime), ParseDateTime(shiftEvent.EndDate, shiftEvent.EndTime)); 
    } 

    private static DateTime ParseDateTime(string date, string time) 
    { 
     string text = string.Concat(date, " ", time); 
     DateTime result; 

     if (DateTime.TryParse(text, out result)) 
     { 
      return result; 
     } 

     throw new ArgumentException("Invalid DateTime", text); 
    } 

    public static Shift StartShift(this ShiftEvent shiftEvent, Tuple<DateTime, DateTime> interval) 
    { 
     return new Shift 
     { 
      EmployeeId = shiftEvent.EmpId, 
      StartOfShiftDate = interval.Item1, 
      EndOfShiftDate = interval.Item2, 
      ShiftEvents = new List<ShiftEvent> { shiftEvent } 
     }; 
    } 
} 

Я игнорировал StartOfShitTime & EndOfShiftTime свойства в классе, потому что ShiftStartOfShiftDate & EndOfShiftDate достаточно для хранения времени информации.

Это решение также предполагает, что в событиях сдвига не происходит перекрытия.

Смежные вопросы