良い。これを行うには多くの方法があり、すべてに長所と短所があります。ここにさらに別の解決策があります。誰かの役に立てば幸いです。
public static IEnumerable<TSource[]> ToRanges<TSource>(
this IEnumerable<TSource> source, Func<TSource, TSource, TSource, bool> isNear)
{
List<TSource[]> result = source./*OrderBy(value => value).*/Aggregate(
new List<TSource[]> { new[] { source.First(), source.First() } },
(ranges, currentValue) => {
TSource[] currentRange = ranges.Last();
TSource previousValue = currentRange[1];
if (isNear(currentRange[0], previousValue, currentValue))
currentRange[1] = currentValue;
else
ranges.Add(new[] { currentValue, currentValue});
return ranges;
}
);
return result;
}
使用例:
List<int> numbers = new List<int>() { 30, 60, 90, 120, 150, 180, 270, 300, 330 };
// split by max difference
numberList.ToRanges(
(first, previous, current) => current - previous <= 30).ToArray();
// { 30, 180 }
// { 270, 330 }
// split by max range
numberList.ToRanges(
(first, previous, current) => current - first <= 90).ToArray();
// { 30, 120 }
// { 150, 180 }
// { 270, 330 }
さらに、整数だけでなく、たとえば単語を最初の文字で分割することもできます。またはDateTime
/ TimeSpan
. またはあなたが望むものは何でも。