score:16

I'd like to recreate a generic version of the excel function AVERAGEIF

Why don't you just use LINQ?

var average = collection.Where(x => x.Something)
                        .Average(x => x.SomeProperty);

Note that this will throw an exception if there are no matching elements. If you don't want that, you could use:

var average = collection.Where(x => x.Something)
                        .DefaultIfEmpty()
                        .Average(x => x.SomeProperty);

It's not clear why you would want to create a separate method for this.

score:0

The following is the answer that works for me:

public double AVERAGEIF<T1,T2>(IEnumerable<T1> average_range, IEnumerable<T2> criteria_range, Func<T2, bool> criteria)
{
    var t1andt2 = average_range.Zip(criteria_range, (l, r) => Tuple.Create<T1, T2>(l, r));      
    return t1andt2.Where(x => criteria(x.Item2)).Average(x => Convert.ToDouble(x.Item1));   
}


void Main()
{   
    var average_range = new List<string>() {"10.1", "10.1", "0", "0"} ; 
    var criteria_range = new List<bool>() {true, true, false, false };  
    Func<bool, bool> criteria = c => c == true;     
    AVERAGEIF(average_range, criteria_range, criteria).Dump();
}

Related Articles