在有序集(数组,列表)上使用LINQ,有没有办法选择或以其他方式使用两个连续项?我在想象语法:
list.SelectTwo((x, y) => ...)
Run Code Online (Sandbox Code Playgroud)
凡x与y位于索引项i和i + 1列表/阵列英寸 可能没有办法做到这一点,我接受这种可能性,但我至少想说我试图找到答案.
我知道我可以使用其他东西和LINQ来实现这一点.
先感谢您.
The*_*kis 11
另一个答案是使用LINQ Skip和Zip.提供一个漂亮而干净的解决方案.
这是绝对正确的,但我想指出它列举了两次来源.根据每个用例的不同,这可能或不重要.如果它对你的情况很重要,这里有一个更长的替代方案,它在功能上等同,但列举了一次来源:
static class EnumerableUtilities
{
public static IEnumerable<TResult> SelectTwo<TSource, TResult>(this IEnumerable<TSource> source,
Func<TSource, TSource, TResult> selector)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (selector == null) throw new ArgumentNullException(nameof(selector));
return SelectTwoImpl(source, selector);
}
private static IEnumerable<TResult> SelectTwoImpl<TSource, TResult>(this IEnumerable<TSource> source,
Func<TSource, TSource, TResult> selector)
{
using (var iterator = source.GetEnumerator())
{
var item2 = default(TSource);
var i = 0;
while (iterator.MoveNext())
{
var item1 = item2;
item2 = iterator.Current;
i++;
if (i >= 2)
{
yield return selector(item1, item2);
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
例:
var seq = new[] {"A", "B", "C", "D"}.SelectTwo((a, b) => a + b);
Run Code Online (Sandbox Code Playgroud)
得到的序列包含"AB","BC","CD".
System.Linq.Enumerable.ZipIEnumerable通过将i每个的第 -th 个元素配对来组合两个s i。所以你只需要在Zip你的列表中使用它的转换版本。
作为一个不错的扩展方法:
using System.Collections.Generic;
using System.Linq;
static class ExtMethods
{
public static IEnumerable<TResult> SelectTwo<TSource, TResult>(this IEnumerable<TSource> source,
Func<TSource, TSource, TResult> selector)
{
return Enumerable.Zip(source, source.Skip(1), selector);
}
}
Run Code Online (Sandbox Code Playgroud)
例子:
Enumerable.Range(1,5).SelectTwo((a,b) => $"({a},{b})");
Run Code Online (Sandbox Code Playgroud)
结果是:
(1,2) (2,3) (3,4) (4,5)
Run Code Online (Sandbox Code Playgroud)