2012-10-17 22 views
8

Czy można to zrobić z linq bez dwukrotnego wyliczenia fooCollection?Linq Wybieranie i agregacja w pojedynczej iteracji

var fooCollection = // get foo 
var selectedIds = new List<int>(); 
var aggregateContent = String.Empty; 

foreach (var f in foo) 
{ 
    selectedIds.Add(foo.Id); 
    aggregateContent += foo.Content 
} 

var results = new FooResults 
{ 
    Content = aggregateContent, 
    SelectedIds = selectedIds 
}; 

return results; 

Odpowiedz

10

Tak, można użyć metody Enumerable.Aggregate:

var result = fooCollection.Aggregate(new FooResult(), 
            (r,f) => 
            { 
             r.SelectedIds.Add(f.Id); 
             r.Content += f.Content; 
             return r; 
            }); 

Ma to tę zaletę, że efektem ubocznym darmo. Nie lubię efektów ubocznych w moim LINQ. =)

+0

Myślę, że go tam przybiłeś Jens. Dzięki. – Nick

+0

+1: Dobre wykorzystanie metody "Agregacja". TIL. –

1

Można to zrobić:

foo.ForEach(x => { selectedIds.Add(x.Id); aggregateContent += x.Content; }); 

Polecam nie łącząc zawartość do łańcucha, ale zamiast używać StringBuilder.

EDIT

Jeśli nie masz bibliotekę rozszerzeń LINQ, która implementuje ForEach dla IEnumerable, tutaj jest metoda można użyć:

public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action) 
{ 
    foreach(T item in enumeration) 
    { 
     action(item); 
    } 
} 
+1

Uwaga: 'ForEach' nie istnieje dla' IEnumerable '. Jest to metoda członkowska 'List '. –

+0

Dziękuję Daniel; Odpowiednio przedłużyłem swoją odpowiedź. –

+1

I sekunda @Daniel's comment: List.Foreach nie ma nic wspólnego z linq. (Pytanie wymaga rozwiązania LINQ). –

2

Jest jedna możliwośc, ale uważam, to hack:

var aggregateContent = String.Empty; 
var selectedIds = foo.Select(x => { aggregateContent += x.Content; 
            return x.Id; }) 
        .ToList(); 

Chciałbym iść z pętli, które już masz. Jest o wiele czystszy, jak każde rozwiązanie LINQ, które możesz wymyślić.

+1

Widzę, o co ci chodzi - używanie Linq do wybierania i zwiększania czegoś nie jest dokładnie CQRS. Jednak mam zamiar pracować z funkcją zbiorczą Linq, ponieważ wyraża to, co staram się robić wyraźnie i czuje się mniej hacky. Dzięki. – Nick

0

To, o co prosisz, to posiadanie instrukcji Linq daje dwa wyniki. Cała idea linq to umożliwienie zwięzłego, funkcjonalnego stylu programowania bez efektów ubocznych.

Jeśli chcesz uzyskać wiele wyników i dobrą wydajność, nie powinieneś używać Linq i używać zwykłego foreach.

+0

Zgadzam się, że nie trzymam w linii z CQRS, ale używając funkcji Aggregate wyrażam funkcję, która jest * tylko * powoduje skutki uboczne - wyniki są jasne. – Nick

Powiązane problemy