Сгруппировать по времени в LINQ - PullRequest
0 голосов
/ 28 ноября 2018

Предположим, у нас есть такой класс:

    class Forecast
    {
      int LocationId;
      int DepartmentId;
      DateTime StartDate;
      DateTime EndDate;
      int CountOfEmployees;
    }

У меня есть список прогнозов: List<Forecasts> forecasts

Список сгруппирован по 15-минутному интервалу, например:

forecast[0] = new Forecast { LocationId = 1, DepartmentId = 1, StartTime = 2018-10-01 06:00:00.000, EndTime = 2018-10-01 06:15:00.000, CountOfEmployees = 2  }
forecast[1] = new Forecast { LocationId = 1, DepartmentId = 1, StartTime = 2018-10-01 06:15:00.000, EndTime = 2018-10-01 06:30:00.000, CountOfEmployees = 1  }
forecast[2] = new Forecast { LocationId = 1, DepartmentId = 1, StartTime = 2018-10-01 06:30:00.000, EndTime = 2018-10-01 06:45:00.000, CountOfEmployees = 3  }
forecast[3] = new Forecast { LocationId = 1, DepartmentId = 1, StartTime = 2018-10-01 06:45:00.000, EndTime = 2018-10-01 07:00:00.000, CountOfEmployees = 1  }
forecast[4] = new Forecast { LocationId = 1, DepartmentId = 1, StartTime = 2018-10-01 07:00:00.000, EndTime = 2018-10-01 07:15:00.000, CountOfEmployees = 2  }
forecast[5] = new Forecast { LocationId = 1, DepartmentId = 1, StartTime = 2018-10-01 07:15:00.000, EndTime = 2018-10-01 07:30:00.000, CountOfEmployees = 2  }
forecast[6] = new Forecast { LocationId = 1, DepartmentId = 1, StartTime = 2018-10-01 07:30:00.000, EndTime = 2018-10-01 07:45:00.000, CountOfEmployees = 5 }
forecast[7] = new Forecast { LocationId = 1, DepartmentId = 1, StartTime = 2018-10-01 07:45:00.000, EndTime = 2018-10-01 08:00:00.000, CountOfEmployees = 3  }
forecast[8] = new Forecast { LocationId = 2, DepartmentId = 2, StartTime = 2018-10-01 06:00:00.000, EndTime = 2018-10-01 06:15:00.000, CountOfEmployees = 2  }
forecast[9] = new Forecast { LocationId = 2, DepartmentId = 2, StartTime = 2018-10-01 06:15:00.000, EndTime = 2018-10-01 06:30:00.000, CountOfEmployees = 1  }
forecast[10] = new Forecast { LocationId = 2, DepartmentId = 2, StartTime = 2018-10-01 06:30:00.000, EndTime = 2018-10-01 06:45:00.000, CountOfEmployees = 3  }
forecast[11] = new Forecast { LocationId = 2, DepartmentId = 2, StartTime = 2018-10-01 06:45:00.000, EndTime = 2018-10-01 07:00:00.000, CountOfEmployees = 1  }
forecast[12] = new Forecast { LocationId = 2, DepartmentId = 2, StartTime = 2018-10-01 07:00:00.000, EndTime = 2018-10-01 07:15:00.000, CountOfEmployees = 2  }
forecast[13] = new Forecast { LocationId = 2, DepartmentId = 2, StartTime = 2018-10-01 07:15:00.000, EndTime = 2018-10-01 07:30:00.000, CountOfEmployees = 2  }
forecast[14] = new Forecast { LocationId = 2, DepartmentId = 2, StartTime = 2018-10-01 07:30:00.000, EndTime = 2018-10-01 07:45:00.000, CountOfEmployees = 5 }
forecast[15] = new Forecast { LocationId = 2, DepartmentId = 2, StartTime = 2018-10-01 07:45:00.000, EndTime = 2018-10-01 08:00:00.000, CountOfEmployees = 3  }

Я бы хотел, чтобы результат был сгруппирован с интервалом в 60 минут, местоположением и отделом вместе с суммированием countOfEmployees.Таким образом, ожидаемый результат должен быть примерно таким:

result[0] = new Forecast { LocationId = 1, DepartmentId = 1, StartTime = 2018-10-01 06:00:00.000, EndTime = 2018-10-01 07:00:00.000, CountOfEmployees = 7  }
result[1] = new Forecast { LocationId = 1, DepartmentId = 1, StartTime = 2018-10-01 07:00:00.000, EndTime = 2018-10-01 08:00:00.000, CountOfEmployees = 12  }
result[2] = new Forecast { LocationId = 2, DepartmentId = 2, StartTime = 2018-10-01 07:00:00.000, EndTime = 2018-10-01 08:00:00.000, CountOfEmployees = 12  }
result[3] = new Forecast { LocationId = 2, DepartmentId = 2, StartTime = 2018-10-01 07:00:00.000, EndTime = 2018-10-01 08:00:00.000, CountOfEmployees = 12  }

Может кто-нибудь указать мне правильное направление?

Ответы [ 4 ]

0 голосов
/ 28 ноября 2018

Вы можете удалить минуты из времени, затем сгруппировать по новым StartTime:

var result = forecast
.GroupBy(g => new { StartTime = g.StartTime.Date.AddHours(g.StartTime.Hour), g.LocationId, g.DepartmentId })
.Select(s => 
    new Forecast()
    {
        LocationId = s.Key.LocationId,
        DepartmentId = s.Key.DepartmentId,
        StartTime = s.Key.StartTime,
        EndTime = s.Max(m => m.EndTime),
        CountOfEmployees = s.Sum(c => c.CountOfEmployees),
    }
)
.OrderBy(o => o.LocationId)
.ThenBy(o => o.DepartmentId)
.ThenBy(o => o.StartTime)
.ToList();

Или с синтаксисом запроса:

var q = from f in forecast
        group f by new 
        { 
            StartTime = f.StartTime.Date.AddHours(f.StartTime.Hour), 
            f.LocationId, 
            f.DepartmentId 
        } into g
        orderby g.Key.LocationId, g.Key.DepartmentId, g.Key.StartTime
        select new Forecast
        {
            LocationId = g.Key.LocationId,
            DepartmentId = g.Key.DepartmentId,
            StartTime = g.Key.StartTime,
            EndTime = g.Max(m => m.EndTime),
            CountOfEmployees = g.Sum(s => s.CountOfEmployees)
        };

вывод:

LocationId: 1, DepartmentId: 1, StartTime: 10/1/2018 6:00:00, EndTime: 10/1/2018 7:00:00, CountOfEmployees: 7
LocationId: 1, DepartmentId: 1, StartTime: 10/1/2018 7:00:00, EndTime: 10/1/2018 8:00:00, CountOfEmployees: 12
LocationId: 2, DepartmentId: 2, StartTime: 10/1/2018 6:00:00, EndTime: 10/1/2018 7:00:00, CountOfEmployees: 7
LocationId: 2, DepartmentId: 2, StartTime: 10/1/2018 7:00:00, EndTime: 10/1/2018 8:00:00, CountOfEmployees: 12

Пример DotNetFiddle

0 голосов
/ 28 ноября 2018

Вы могли бы сделать что-то подобное, предполагая, что ваш интервал всегда будет начинаться от 00 минут до 60 минут, а не, скажем, с 6:15 до 7: 15.

var result = forecast.GroupBy(x=>new {x.StartTime.Hour, x.LocationId, x.DepartmentId})
                    .Select(x=> new Forecast
                                { 
                                    LocationId = x.Key.LocationId, 
                                    DepartmentId = x.Key.DepartmentId, 
                                    StartTime =  x.ToList().OrderBy(e=>e.StartTime).First().StartTime,
                                    EndTime =  x.ToList().OrderBy(e=>e.EndTime).Last().EndTime,
                                    CountOfEmployees = x.ToList().Sum(c=>c.CountOfEmployees) 
                                    });
0 голосов
/ 28 ноября 2018

Это должно работать.Как упомянул @SeM, вам нужно показать свое исследование.Ваш вопрос не показал никакой работы.

var results = from foreCastSelector in foreCasts
          group foreCastSelector by new
          {
              LocationId = foreCastSelector.LocationId,
              DepartmentId = foreCastSelector.DepartmentId,
              StartDate = foreCastSelector.StartDate.AddMinutes(-1 * foreCastSelector.StartDate.Minute),
              EndDate = foreCastSelector.StartDate.AddMinutes(-1 * foreCastSelector.StartDate.Minute).AddHours(1)
          } into gcs
          select new Forecast
          {
              LocationId = gcs.Key.LocationId,
              DepartmentId = gcs.Key.DepartmentId,
              StartDate = gcs.Key.StartDate,
              EndDate = gcs.Key.EndDate,
              CountOfEmployees = gcs.Sum(r => r.CountOfEmployees)
              };

foreach (var result in results)
{
    Console.WriteLine(result.LocationId + " | " + result.DepartmentId + " | "
        + result.StartDate.ToString() + " | "
       + result.EndDate.ToString() + " | "
       + result.CountOfEmployees);
}
0 голосов
/ 28 ноября 2018

Вы можете попытаться использовать linq select с group by

Установить группировку времени в linq GroupBy для вашей логики для EndTime, StartTime, LocationId

StartTime и EndTime за каждый час.

var result = forecast
.GroupBy(_ => new {
    _.LocationId,
    StartTime = new DateTime(_.StartTime.Year,
                              _.StartTime.Month,
                              _.StartTime.Day,
                              _.StartTime.Hour,0,0,0),
    EndTime = new DateTime(_.StartTime.Year,
                              _.StartTime.Month,
                              _.StartTime.Day,
                              _.StartTime.Hour + 1, 0, 0, 0)
})
.Select(x => new {
    x.Key.LocationId,
    x.Key.StartTime,
    x.Key.EndTime,
    CountOfEmployees = x.Sum(y=>y.CountOfEmployees)});

c # online

Результат

LocationId : 1 StartTime : 10/1/2018 6:00:00 AM EndTime : 10/1/2018 7:00:00 AM  CountOfEmployees : 7
LocationId : 1 StartTime : 10/1/2018 7:00:00 AM EndTime : 10/1/2018 8:00:00 AM  CountOfEmployees : 12
LocationId : 2 StartTime : 10/1/2018 6:00:00 AM EndTime : 10/1/2018 7:00:00 AM  CountOfEmployees : 7
LocationId : 2 StartTime : 10/1/2018 7:00:00 AM EndTime : 10/1/2018 8:00:00 AM  CountOfEmployees : 12
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...