Ronald Arndt

C# Snippet - GroupByGap

15 de junho de 2025

#csharp #snippet #linq

Este snippet demonstra como agrupar elementos de uma lista com base em um intervalo de diferença entre eles. É útil quando você deseja agrupar números ou objetos que estão próximos uns dos outros.

Neste exemplo, usamos uma expressão para selecionar uma propriedade do tipo DateTime de cada item e agrupamos os itens que estão dentro de um intervalo máximo especificado, mas você pode adaptá-lo para outros tipos de dados conforme necessário.

public static List<List<T>> GroupByGap<T>(T[] items, Expression<Func<T, DateTime>> selector, TimeSpan maxGap)
{
if (items == null || items.Length == 0)
{
return [];
}
var sorted = items.AsQueryable().OrderBy(selector).ToArray();
var groups = new List<List<T>>();
var currentGroup = new List<T> { sorted[0] };
var selectorFunc = selector.Compile();
for (var i = 1; i < sorted.Length; i++)
{
if (selectorFunc(sorted[i]) - selectorFunc(sorted[i - 1]) <= maxGap)
{
currentGroup.Add(sorted[i]);
}
else
{
groups.Add(currentGroup);
currentGroup = [sorted[i]];
}
}
groups.Add(currentGroup);
return groups;
}

Uso

var items = new[]
{
new { Id = 1, Date = new DateTime(2023, 1, 1) },
new { Id = 2, Date = new DateTime(2023, 1, 2) },
new { Id = 3, Date = new DateTime(2023, 1, 5) },
new { Id = 4, Date = new DateTime(2023, 1, 10) },
};
var groupedItems = GroupByGap(items, x => x.Date, TimeSpan.FromDays(2));
foreach (var group in groupedItems)
{
Console.WriteLine($"Group: {string.Join(", ", group.Select(x => x.Id))}");
}
// Saída esperada:
// Group: 1, 2
// Group: 3
// Group: 4

Neste caso específico, os itens serão agrupados em três listas: uma contendo os IDs 1 e 2 (porque estão dentro de um intervalo de 2 dias), outra contendo o ID 3 e outra contendo o ID 4 (porque a diferença entre eles é maior que 2 dias).