You can use the special Select overload, which allows you to use the element index and the GroupBy method to split the list into groups. Each group will have two elements. Here is an extension method that does this:
public static class ExtensionMethods { public static IEnumerable<TResult> SelectTwo<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TSource, TResult> selector) { return source.Select((item, index) => new {item, index}) .GroupBy(x => x.index/2) .Select(g => g.Select(i => i.item).ToArray()) .Select(x => selector(x[0], x[1])); } }
And you can use it as follows:
var list = new[] {1, 2, 3, 4, 5, 6}; var result = list.SelectTwo((x, y) => x + y).ToList();
This will return {3,7,11}
Note that the above method groups the data in memory before proceeding with the results. If you have large data sets, you might want to use the streaming approach (exit data, since the data from the source is being listed), here is an example:
public static class ExtensionMethods { public static IEnumerable<TResult> SelectTwo<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TSource, TResult> selector) { bool first_item_got = false; TSource first_item = default(TSource); foreach (var item in source) { if (first_item_got) { yield return selector(first_item, item); } else { first_item = item; } first_item_got = !first_item_got; } } }