在迭代时是否有Linq方式知道序列中的下一个元素是什么?作为一个具体的例子,假设我有一个整数列表,我想计算每个元素和它的后继之间的差异,所以例如我希望能够写
var myList = new List<int>() { 1,3,8,2,10 };
var differences = myList.Select( ml => ml.Next() - ml ) // pseudo-code, obviously
Run Code Online (Sandbox Code Playgroud)
我想要的结果是列表{2,5,-6,8}.
显然这在for循环中是微不足道的,但任何人都可以想到Linq中的一个简洁的单行程来完成这项工作吗?
Luk*_*keH 41
var differences = myList.Zip(myList.Skip(1), (x, y) => y - x);
Run Code Online (Sandbox Code Playgroud)
如果您在使用框架的旧版本,和/或你想要一个稍微这样做的更有效的方式,那么你可以创建一个简单的扩展方法:
var differences = myList.Pairwise((x, y) => y - x);
// ...
public static class EnumerableExtensions
{
public static IEnumerable<T> Pairwise<T>(
this IEnumerable<T> source, Func<T, T, T> selector)
{
if (source == null) throw new ArgumentNullException("source");
if (selector == null) throw new ArgumentNullException("selector");
using (var e = source.GetEnumerator())
{
if (!e.MoveNext()) throw new InvalidOperationException("Sequence cannot be empty.");
T prev = e.Current;
if (!e.MoveNext()) throw new InvalidOperationException("Sequence must contain at least two elements.");
do
{
yield return selector(prev, e.Current);
prev = e.Current;
} while (e.MoveNext());
}
}
}
Run Code Online (Sandbox Code Playgroud)
var differences = myList
.Take(myList.Count - 1)
.Select((v, i) => myList[i + 1] - v);
Run Code Online (Sandbox Code Playgroud)
假设列表至少有2个项目.