tags:

views:

120

answers:

2

Given the following object:

public class Product {
   string Name {get;} 
   int Quantity {get;}
}

using Linq, how would I query a List<Product> until I got a sum >= a given quantity? In other words, if my list looked like

Name     Quantity
-----------------
prod1       5
prod2       6
prod7       7

I want to query the List and pull instances until I get a Sum >=8. In this case I'd get the first two items in the List. If I wanted sum >= 12, I'd get all three.

I know I can write a loop to do this for me, but I was fantasizing that there was some slick one-liner using Linq to achieve the same thing.

Thanks

+7  A: 

Here is a quick 2 liner.

var sum = 0;
var query = col.Where(x => { var temp = sum; sum += x.Quantity; return temp < 500; });

Replace 500 with the constant or variable of your choosing.

EDIT

Here is mquander's more efficient solution

var sum = 0;
var query = col.TakeWhile(x => { var temp = sum; sum += x.Quantity; return temp < 500; });
JaredPar
That is sweet..
jlembke
It would be more efficient to do the exact same thing except instead of .Where(), to use .TakeWhile(), and check whether the sum at the start is greater than 500, not at the end (else you'll take one too few elements.) Then the iteration would cease when the 500 barrier is broken.
mquander
@mquander, both good points, updated the answer
JaredPar
TakeWhile() is much better. Good one @mquander!
GraemeF
Even better! Thanks guys!
jlembke
A: 

You just create a variable to hold the sum, then add to it as each item in the list is tested with the where clause:

int sum = 0;
from product in list where (sum += product.Quantity) < 8 select product
GraemeF
Interestingly, the more I use Linq, the more I find myself leaning toward the extension method syntax, except in cases where I'm querying the source in a very sql-ish fashion. I wonder if that's a common pattern of linq usage?
Greg D
Possibly - it's still early days for me.
GraemeF
That pattern of usage is what I've experienced... There's little point to writing that from and select clause if you just want to filter. I revert back to the query comprehension syntax to use "let" clauses though.
David B