Linq: List of double values - differences between

2019-02-24 05:03发布

问题:

i have a list of double values...

1.23, 1.24, 1.78, 1,74...

so i want to calculate the differences between the successor -> only adding (negative values should be firstly positive)... above 4 values would be 0,01 +0,53 (-)-0,04 (-) -> to make it positive...

with an for-loop, it is easy... any idea how to solve it with linq?

回答1:

I'm not sure what you mean about the negative bits, but this might do what you want. It's horrible because it uses side effects, but...

double prev = 0d;
var differences = list.Select(current =>
    {
       double diff = prev - current;
       prev = current;
       return Math.Abs(diff);
    }).Skip(1);

(The first value is skipped because it just gives the difference between the first original value and 0d.)

EDIT: What might be slightly nicer would be an extension method to project based on pairs of elements. This isolates the side-effects in one place, which is fine:

using System.Collections.Generic;

// This must be a non-nested type, and must be static to allow the extension
// method.
public static class Extensions
{
    public static IEnumerable<TResult> SelectPairs<TSource, TResult>
        (this IEnumerable<TSource> source,
         Func<TSource, TSource, TResult> selector)
    {
        using (IEnumerator<TSource> iterator = source.GetEnumerator())
        {
           if (!iterator.MoveNext())
           {
               yield break;
           }
           TSource prev = iterator.Current;
           while (iterator.MoveNext())
           {
               TSource current = iterator.Current;
               yield return selector(prev, current);
               prev = current;
           }
        }
    }
}

To use this in your particular case, you'd do:

var differences = list.SelectPairs((x, y) => Math.Abs(x-y));


回答2:

You could use the overload of the Select method that supplies the index to the function, so that you can access the previous value in the array:

double sum = values.Skip(1).Select((n, i) => Math.Abs(n - values[i])).Sum();

Not a perfectly "clean" LINQ solution (Jon's SelectPairs extension looks nicer), but I think that it's the easiest way to form the pairs.