/// <summary> /// Computes the mean average of the sequence of values that are /// obtained by invoking a transform function on each element of the input sequence. /// </summary> /// <remarks>The values returned by the transform function must support the Add and Divide(Int32) operators</remarks> public static TValue Average <TSource, TValue>(this IEnumerable <TSource> source, Func <TSource, TValue> selector) { source.ThrowIfNull("source"); selector.ThrowIfNull("selector"); int count = 0; TValue sum = Operator <TValue> .Zero; // not the same as default(T); think "int?" foreach (TSource item in source) { if (Operator.AddIfNotNull(ref sum, selector(item))) { count++; } } if (count == 0) { sum = default(TValue); if (sum != null) { throw new InvalidOperationException("Cannot perform non-nullable average over an empty series"); } return(sum); } else { return(Operator.DivideInt32(sum, count)); } }
/// <summary> /// Returns a future to the average of a sequence of values that are /// obtained by taking a transform of the input sequence /// </summary> /// <remarks>Null values are removed from the average</remarks> public static IFuture <TResult> Average <TSource, TResult>(this IDataProducer <TSource> source, Func <TSource, TResult> selector) { source.ThrowIfNull("source"); selector.ThrowIfNull("selector"); Future <TResult> ret = new Future <TResult>(); TResult sum = Operator <TResult> .Zero; int count = 0; // should this be long? Would demand a Operator.DivideInt64 source.DataProduced += item => { if (Operator.AddIfNotNull(ref sum, selector(item))) { count++; } }; source.EndOfData += () => { if (count == 0) { // check if Nullable<T> by seeing if default(T) is // nullable; if so, return null; otherwise, throw sum = default(TResult); if (sum != null) { throw new InvalidOperationException("Cannot perform non-nullable average over an empty series"); } ret.Value = sum; // null } else { ret.Value = Operator.DivideInt32(sum, count); } }; return(ret); }
/// <summary> /// Computes the sum of the sequence of values that are /// obtained by invoking a transform function on each element of the input sequence. /// </summary> /// <remarks>The values returned by the transform function must support the Add operator</remarks> public static TValue Sum <TSource, TValue>(this IEnumerable <TSource> source, Func <TSource, TValue> selector) { source.ThrowIfNull("source"); selector.ThrowIfNull("selector"); TValue sum = Operator <TValue> .Zero; // not the same as default(T); think "int?" foreach (TSource item in source) { Operator.AddIfNotNull(ref sum, selector(item)); } return(sum); }
/// <summary> /// Returns a future to the sum of a sequence of values that are /// obtained by taking a transform of the input sequence /// </summary> /// <remarks>Null values are removed from the sum</remarks> public static IFuture <TResult> Sum <TSource, TResult>(this IDataProducer <TSource> source, Func <TSource, TResult> selector) { source.ThrowIfNull("source"); selector.ThrowIfNull("selector"); Future <TResult> ret = new Future <TResult>(); TResult sum = Operator <TResult> .Zero; source.DataProduced += item => { Operator.AddIfNotNull(ref sum, selector(item)); }; source.EndOfData += () => ret.Value = sum; return(ret); }