2009-10-30 15 views
10

otrzymuje następujące obiektu:LINQ: Jak kwerendy przedmioty z kolekcji aż suma osiągnie pewną wartość

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

użyciu LINQ, jak chciałbym kwerendy List<Product> dopóki nie dostał sumę >= dana ilość? Innymi słowy, jeśli moja lista wyglądała

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

Chcę kwerendy listy i ciągnąć instancje aż dostaję Suma >=8. W takim przypadku dostanę pierwsze dwie pozycje na liście. Gdybym chciał sumę >= 12, dostałbym wszystkie trzy.

Wiem, że mogę napisać pętlę, aby zrobić to dla mnie, ale fantazjowałem, że był jakiś zgrabny jednolinijkowy używający Linq do osiągnięcia tego samego.

Dzięki

Odpowiedz

16

Oto szybki 2 liniowej.

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

Zamień 500 na wybraną stałą lub zmienną.

EDIT

Oto mquander bardziej efektywne rozwiązanie

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

To jest słodkie .. – jlembke

+9

Byłoby bardziej wydajne zrobić dokładnie to samo, z wyjątkiem zamiast. Gdzie(), aby użyć .TakeWhile(), i sprawdź, czy suma na początku jest większa niż 500, a nie na końcu (w przeciwnym razie użyjesz jednego za mało elementów.) Następnie iteracja ustałaby, gdy bariera 500 jest złamany. – mquander

+0

@mquander, oba dobre punkty, zaktualizowano odpowiedź – JaredPar

1

Wystarczy utworzyć zmienną trzymać sumę, a następnie dodać do niej, jak każdej pozycji na liście jest testowany z klauzulą ​​where :

int sum = 0; 
from product in list where (sum += product.Quantity) < 8 select product 
+0

Co ciekawe, im bardziej używam Linq, tym bardziej znajduję się skłaniającą się ku składni metody rozszerzenia, z wyjątkiem przypadków, w których pytam o źródło w bardzo sql-ish. Zastanawiam się, czy to powszechny wzór użycia linq? –

+0

Prawdopodobnie - to dla mnie jeszcze wczesne dni. – GraemeF

+2

Ten wzór użycia jest tym, czego doświadczam ... Nie ma sensu pisać tego z klauzuli "wybierz i zaznacz", jeśli chcesz tylko filtrować. Powracam do składni ze zrozumieniem zapytań, aby używać klauzul "let". –