Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq way to get piecewise difference between element and next element in list

Tags:

c#

linq

Is there a Linq way of knowing what the next element in the sequence is while iterating? As a concrete example, say I have a list of ints, and I want to calculate the difference between each element and its successor, so for example I would like to be able to write

var myList = new List<int>() { 1,3,8,2,10 }; var differences = myList.Select( ml => ml.Next() - ml ) // pseudo-code, obviously 

where the result I want is a list { 2,5,-6,8 }.

Obviously this is trivial in a for loop, but can anyone think of a neat one-liner in Linq to do this job?

like image 625
Aidan Avatar asked Oct 19 '10 15:10

Aidan


2 Answers

If you're using .NET 4 then you could Zip and Skip:

var differences = myList.Zip(myList.Skip(1), (x, y) => y - x); 

If you're using an older version of the framework, and/or you wanted a slightly more efficient way of doing this, then you could create a simple extension method:

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());         }     } } 
like image 126
LukeH Avatar answered Oct 14 '22 04:10

LukeH


var differences = myList     .Take(myList.Count - 1)     .Select((v, i) => myList[i + 1] - v); 

Assuming the list has at least 2 items.

like image 41
Yuriy Faktorovich Avatar answered Oct 14 '22 03:10

Yuriy Faktorovich