以下是我想要分组的数据。
Start End
2 4
26 30
5 9
20 24
18 19
因为我有18 - 19和20 - 24.我会将这两个加在一起作为18 - 24.在这种情况下,规则是(a,b)=> b.start - a.end = 1,结果将是
Start End
18 24
2 9
26 30
EDIT在下面的评论中添加了最后一个结果行。
答案 0 :(得分:5)
因此,我们将从名为GroupWhile
的辅助方法开始。它将提供一个谓词,接受序列,前一个和当前的两个项目。如果该谓词返回true,则当前项目与前一项目进入同一组。如果没有,它会启动一个新组。
public static IEnumerable<IEnumerable<T>> GroupWhile<T>(
this IEnumerable<T> source, Func<T, T, bool> predicate)
{
using (var iterator = source.GetEnumerator())
{
if (!iterator.MoveNext())
yield break;
List<T> list = new List<T>() { iterator.Current };
T previous = iterator.Current;
while (iterator.MoveNext())
{
if (!predicate(previous, iterator.Current))
{
yield return list;
list = new List<T>();
}
list.Add(iterator.Current);
previous = iterator.Current;
}
yield return list;
}
}
一旦我们有了这个,我们可以在开始时按顺序排序项目,然后在结束日期之前对它们进行分组,同时将前一个范围的结束与下一个范围的开始重叠,然后根据组开始将每个组折叠到新的范围内和结束价值。
var collapsedRanges = ranges.OrderBy(range => range.Start)
.ThenBy(range => range.End)
.GroupWhile((prev, cur) => prev.End + 1 >= cur.Start)
.Select(group => new Range()
{
Start = group.First().Start,
End = group.Select(range => range.End).Max(),
});