另一种方法是使用 Enumerator 并编写自定义 LINQ 扩展方法。
这种方法效率更高,因为它消除了集合的多次枚举:
public static class LinqExtensions
{
public static IEnumerable<Tuple<T, T>> GroupBy2<T>(this IEnumerable<T> source)
{
var enumerator = source.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
T first = enumerator.Current;
if (!enumerator.MoveNext()) {
yield return new Tuple<T, T>(first, default(T));
yield break;
}
T second = enumerator.Current;
yield return new Tuple<T, T>(first, second);
}
}
finally
{
if (enumerator != null)
enumerator.Dispose();
}
}
}
使用示例:
var data = new List<double>() { 32.00, 95.00, 60.00, 14.00, 62.00 };
// As Tuple<double, double>[] array:
var results = data.OrderByDescending(x => x).GroupBy2().ToArray();
// Iterate through IEnumerable<Tuple<double, double>>:
foreach (var pair in data.OrderByDescending(x => x).GroupBy2())
{
Console.WriteLine($"{pair.Item1} {pair.Item2}");
}
结果:
32 95
60 14
62 0
您可以为非偶数项提供另一种行为而不是 default(T)。
例如,如果 pair 不存在,此实现将 null 作为第二个元组项返回,但它不适用于类。
public static IEnumerable<Tuple<T, T?>> GroupBy2<T>(this IEnumerable<T> source)
where T : struct
{
var enumerator = source.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
T first = enumerator.Current;
if (!enumerator.MoveNext()) {
yield return new Tuple<T, T?>(first, null);
yield break;
}
T second = enumerator.Current;
yield return new Tuple<T, T?>(first, second);
}
}
finally
{
if (enumerator != null)
enumerator.Dispose();
}
}