Чтобы создать более удобное решение Linqy, вы можете начать с создания универсального метода группировки, который группирует последовательные элементы последовательности на основе определенных пользователем критериев. Ниже приведена простая реализация такого метода:
public static IEnumerable<List<TSource>> GroupConsecutive<TSource>(
this IEnumerable<TSource> source,
Func<TSource, IList<TSource>, bool> predicate)
{
List<TSource> list = null;
IList<TSource> readOnlyList = null;
foreach (var item in source)
{
if (list == null || !predicate(item, readOnlyList))
{
if (list != null) yield return list;
list = new List<TSource>();
readOnlyList = new ReadOnlyCollection<TSource>(list);
}
list.Add(item);
}
if (list != null) yield return list;
}
predicate
- это лямбда, которая принимает текущий элемент вместе с текущей группой и должна возвращать логическое значение, обозначающее, принадлежит ли элемент кгруппа или нет. true
означает, что она принадлежит группе, а false
означает, что она не принадлежит, поэтому текущая группа была завершена и должна быть создана новая, содержащая изначально только текущий элемент.
Затем вы можете использовать этот метод для решения вашей первоначальной проблемы, отсортировав объекты по DueDate
, а затем сгруппировав их, сравнив DueDate
каждого из них с DueDate
первого элемента текущей группы. Если TimeSpan
меньше или равно 60 минутам, то элемент принадлежит текущей группе. Этот алгоритм должен производить минимальное количество групп.
var source = new List<(int Id, DateTime DueDate)>();
source.Add((1, new DateTime(2020, 1, 1, 1, 30, 0)));
source.Add((2, new DateTime(2020, 1, 1, 1, 40, 0)));
source.Add((3, new DateTime(2020, 1, 1, 3, 20, 0)));
source.Add((4, new DateTime(2020, 1, 1, 4, 10, 0)));
source.Add((5, new DateTime(2020, 1, 1, 5, 10, 0)));
var groups = source
.OrderBy(x => x.DueDate)
.GroupConsecutive((item, group) =>
(item.DueDate - group[0].DueDate).Duration().TotalMinutes <= 60);
foreach (var group in groups)
{
Console.WriteLine($"Group: {String.Join(", ", group)}");
}
Вывод:
Группа: (1, 01.01.2020 01:30:00), (2,01.012020 01:40:00)
Группа: (3, 01.012020 03:20:00), (4, 01.012020 04:10:00)
Группа:(5.01.012020 05:10:00)