views:

51

answers:

3

I have a query that sums and aggregates alot of data something like this:

var anonType = from x in collection
               let Cars = collection.Where(c=>c.Code == "Cars")
               let Trucks = collection.Where(c=>c.Code == "Trucks")
               select new { 
                           Total = collection.Sum(v=>v.Amount),
                           CarValue = Cars.Sum(v=>v.Amout),
                           TruckValue = Trucks.Sum(v=>v.Amount),
                           CarCount = Cars.Count(),
                           TruckCount = Trucks.Count()
               };

I find it really weird that I have to declare the range variable x, especially if I'm not using it. So, am I doing something wrong or is there a different format I should be following?

+1  A: 

You declare a range variable no matter the looping construct:

foreach(var x in collection)

or

for(var index = 0; index < collection.Count; index++)

or

var index = 0;

while(index < collection.Count)
{
    //...

    index++;
}

Queries are no different. Just don't use the variable, it doesn't hurt anything.

Bryan Watts
+3  A: 

I could be wrong, but from your usage, I don't think you want to do a traditional query expression syntax query with your collection anyway, as it appears you are only looking for aggregates. The way you have it written, you would be pulling multiple copies of the aggregated data because you're doing it for each of the items in the collection. If you wished, you could split your query like this (sample properties thrown in)

var values = collection.Where(c => c.Code == "A");
var anonType = new
               {
                   Sum = values.Sum(v => v.Amount),
                   MinimumStartDate = values.Min(v => v.StartDate),
                   Count = values.Count()
               };
Anthony Pegram
Thats an interesting thought that it might be doing the aggregation for each of the items in the collection. Any thoughts on where I could look to find out if it does in fact do this?
itchi
When you say `from x in collection`, what is essentially going to happen under the hood is `foreach (var x in collection)` (with whatever filtering criteria you have thrown in). So if you have 20 items in the collection, you'll get (unless otherwise filtered) 20 aggregated anonymous types, as `anonType` will not be a single record but rather an `IEnumerable<Anonymous>`.
Anthony Pegram
+1  A: 

So, am I doing something wrong?

Your query is not good. For each element in the collection, you are enumerating the collection 5 times (cost = 5*n^2).

Is there a different format I should be following?

You could get away with enumerating the collection 5 times (cost = 5n).

IEnumerable<X> cars = collection.Where(c => c.Code == "Cars");
IEnumerable<X> trucks = collection.Where(c => c.Code == "Trucks");

var myTotals = new 
{
  Total = collection.Sum(v => v.Amount),
  CarValue = cars.Sum(v => v.Amount),
  TruckValue = trucks.Sum(v => v.Amount,
  CarCount = cars.Count(),
  TruckCount = trucks.Count()
};
David B
+1 for (cost = 5*n^2). But I think this answer is very similar to Anthony's.
itchi
Ah, it is similiar... I didn't notice because Anthony answered the original question and I answered the editted question.
David B