Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq Select and Aggregate within a single iteration

Tags:

c#

linq

aggregate

Is there a way to do this with linq without enumerating the fooCollection twice?

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;
like image 628
Nick Avatar asked Oct 17 '12 14:10

Nick


3 Answers

Yes, you can use the Enumerable.Aggregate method:

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

This has the benefit of being side-effect free. I dislike side effects in my LINQ. =)

like image 133
Jens Avatar answered Oct 22 '22 15:10

Jens


There is one possiblity, but I consider it a hack:

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

I would go with the loop you already have. It is much cleaner as any LINQ solution you could come up with.

like image 45
Daniel Hilgarth Avatar answered Oct 22 '22 15:10

Daniel Hilgarth


You could do this:

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

I would recommend not concatenating the Content into a string, but to use a StringBuilder instead.

EDIT

If you don't have a LINQ extension library that implements ForEach for IEnumerable, here is a method you can use:

public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action) 
{ 
    foreach(T item in enumeration) 
    { 
        action(item); 
    } 
} 
like image 26
Roy Dictus Avatar answered Oct 22 '22 14:10

Roy Dictus