tags:

views:

71

answers:

1

In my new project, I`m writing a lot of linq. And I have a lot of linq queries like this:

...
group new {A, B} by new {....}
into g
// Calculate select claw
let SumVal1 = g.Sum(x => x.A.Value1 * func(x.A, x.B)) / g.Sum(x => func(x.A, x.B))
let SumVal2 = g.Sum(x => x.A.Value2 * func(x.A, x.B)) / g.Sum(x => func(x.A, x.B))
let SumVal3 = g.Sum(x => x.A.Value3 * func(x.A, x.B)) / g.Sum(x => func(x.A, x.B))
....
// Here could be some calculation, that are not patterned, like:
let NotPatternedSum1 = g.Sum(x => x.A.Duration)
...
select new {SumVal1, SumVal2, SumVal3, ..., NotPatternedSum, ...}

How can I simplify this? I have many queries with this pattern (Sum(A*func)/Sum(func)) - how can I introduce this to a single method or delegate?

Maybe you've seen some advises for a designing big linq queries? My code is consists of 95% linq (I`m moving db logic to a client). Pls, give me some tips, maybe non trivial =)

And I want to avoid using non-anonymous types

+4  A: 

Something like this (assuming int values; hopefully most of your values are with the same type - it's a pain to do this generically).

public static int DividingSum<T>(this IEnumerable<T> source,
    Func<T, int> f1, Func<T, int> f2)
{
    return source.Sum(t => f1(t) * f2(t)) / source.Sum(t => f2(t));
}

If possible, come up with better names than f1 and f2 though :)

Calling:

let SumVal1 = g.DividingSum(x => x.A.Value1, func)

This is assuming LINQ to Objects... LINQ to SQL (or Entities) would make this harder, but probably not impossible.

EDIT: Responding to the comment, you'd just change the call to:

let SumVal1 = g.DividingSum(x => x.A.Value1, x => func(x.A, x.B))
Jon Skeet
Thnx, pretty simple - but I have a problem with given implementation.My g value is IEnumerable<anonymous type> (or IGrouping<anonymous type>?) and my func can`t accept anonymous types as arguments
Archeg
@Archeg: I've edited the answer to add an extra example at the bottom.
Jon Skeet
Wow, thnx. As to me - very cool stuff, I was very surprised when VS showed list of members x.A, x.B in last lambda =) Thnx a lot
Archeg
Could rename "DividingSum" to "WeightedAverage" and the first selector to x and second selector to w
erash
@erash: Possibly. I'll let Arheg decide that :)
Jon Skeet