How to calculate zeros changes using Linq

I need to calculate the changes in the time series of zero numbers. The following code does the job:

public static double?[] GetChanges(double?[] x) { if(x.Length == 1) throw new Exception("Time Series Too Short"); var ret = new double?[x.Length - 1]; for (int i = 1; i < x.Length; i++) { ret[i-1] = (x[i - 1].HasValue && x[i].HasValue) ? x[i] - x[i - 1] : null; } return ret; } 

Is there a better way to achieve this with Linq? The library uses .Net 3.5. I can’t use Zip right now because it is happening with .Net 4.

Edit: following the advice of mquander and Eric Lippert, I came up with the following code that works on 3.5:

 public class Tuple<T> { public Tuple(T first) { First = first; } public T First { get; set; } } public class Tuple<T, T2> : Tuple<T> { public Tuple(T first, T2 second) : base(first) { Second = second; } public T2 Second { get; set; } public static Tuple<T1, T2> New<T1, T2>(T1 t1, T2 t2) { return new Tuple<T1, T2>(t1, t2); } } public static class EnumerableExtensions { public static IEnumerable<Tuple<T, T>> Pairs<T>(this IEnumerable<T> seq) { using (var enumerator = seq.GetEnumerator()) { enumerator.MoveNext(); var prior = enumerator.Current; while (enumerator.MoveNext()) { yield return Tuple<T, T>.New(prior, enumerator.Current); prior = enumerator.Current; } } } } 

I use this code as follows:

  public static IEnumerable<double?> GetChanges2(double?[] x) { if (x.Length == 1) throw new Exception("Time Series Too Short"); return x.Pairs().Select(p => p.Second - p.First); } 

Any suggestions for further improvement are welcome. I will be back when I have VS2010 and .Net 4 so that I can try the approaches suggested in both answers.

Thanks!

+4
source share
3 answers

Another idea (inspired by this answer) is to save the previous element in the captured variable:

 static IEnumerable<double?> GetChanges(IEnumerable<double?> x) { double? previous = x.First(); return x.Skip(1).Select(d => { double? result = d - previous; previous = d; return result; }); } 

This should work because the captured variable is "hidden" in the function.

+1
source

Maybe just

 Enumerable.Zip( x.Skip(1), x, (a, b) => (a.HasValue && b.HasValue) ? (a - b) : null) ) 

?

By the way, I would use only doubles and double.NaN instead of zeros. Thus, the code can be simplified to simple

 Enumerable.Zip(x.Skip(1), x, (a, b) => a - b) 

in this and possibly in some other places.

EDIT:
Following @Eric Lippert's advice, removing null checks is possible even for the Nullable case. So the answer will be just

 Enumerable.Zip(x.Skip(1), x, (a, b) => a - b) 

even in this case.

+3
source

Not really. I would do it your way. If you feel particularly functional, you could define the Pairs method on IEnumerable<T> , which splits the sequence into a series of consecutive overlapping pairs, and then maps each pair to the deltas between its first and second value.

EDIT as an example was requested:

 public static class EnumerableExtensions { public static IEnumerable<Tuple<T, T>> Pairs<T>(this IEnumerable<T> seq) { using (var enumerator = seq.GetEnumerator()) { enumerator.MoveNext(); var prior = enumerator.Current; while (enumerator.MoveNext()) { yield return Tuple.Create(prior, enumerator.Current); prior = enumerator.Current; } } } } 

Then GetChanges comes down to:

 var changes = values.Pairs().Select(x => x.Item2 - x.Item1); 

(Note: my implementation returns an empty sequence instead of throwing an exception if values contains less than two values.)

(edit again - clear NULL processing at the end, thanks Eric for pointing out!)

+1
source

All Articles