1

In my application I'm calculating the geometric mean a few different places, and would like to have the implementation in one place, so as to cause less confusion for maintainers. For performance reasons I need the calculation to happen in the database, so fetching the data and running GeoMean() in C# is not an option.

However, I can't figure out how to write an extension method that I can use in my code. The query looks something like this:

data.GroupBy(a => a.Foo)
    .Select(a => new {
        Id = a.Foo,
        Mean = a.GeoMean(b => b.Value)
    });  

I seem to have figure out I must use a.AsQueryable().GeoMean(), and an extension method looking something like this:

public static double GeoMean<T>(this IQueryable<T> source, Expression<Func<T, double>> fn)
{
    return Math.Exp(source.Average(i => Math.Log(fn(i))));
}

However, since it's expected to return double it complains that fn is an Expression. If I change the return type to Expression<Func<double>> I've merely moved the problem to the Select in my query, so I probably need to do something to it, but what?

Is this even possible? Should I just accept that I'll have to duplicate the code every time I need the calculation?

atiyar
  • 7,762
  • 6
  • 34
  • 75
BioTronic
  • 2,279
  • 13
  • 15

1 Answers1

-1
public static double GeoMean<T>(this IQueryable<T> source, Expression<Func<T, double>> selector)
{
    var averageOfLogValues = source
        .Select(selector)
        .Select(value => Math.Log(value))
        .Average();

    return Math.Exp(averageOfLogValues);
}
Timothy Stepanski
  • 1,186
  • 7
  • 21
  • Problem is, inside `Select`, I have an `IGrouping`, which I can't simply pass to `GeoMean` and pretend it's an `IQueryable` (.AsQueryable gives ArgumentException: Expression of type IGrouping cannot be used for parameter of type IQueryable). – BioTronic Mar 04 '21 at 08:21
  • IGrouping is a singular "group." It has a single key and enumerable of elements. GroupBy gives you an IEnumerable/IQueryable of IGrouping. So, your selector would need to select from the grouping itself. Unless you wanted the grouping to occur inside GeoMean? Pay attention to your IDE's suggestions, it will help you. – Timothy Stepanski Mar 04 '21 at 14:48