Linq Select and Aggregate in one iteration

Is there a way to do this with linq without re-enumerating fooCollection ?

 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; 
+8
c # linq aggregate
source share
4 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 can be a side effect. I don't like the side effects in my LINQ. =)

+10
source share

There is one possibility, but I consider this a hack:

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

I would go with the cycle that you already have. It is much cleaner than any LINQ solution you could come up with.

+2
source share

You can do it:

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

I would recommend not concatenating Content into a string, but rather using StringBuilder .

EDIT

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

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

What you are asking is for the Linq statement to produce two results. The whole idea of ​​linq is to provide a concise, functional programming style without side effects.

If you need multiple results and good performance, you should not use Linq and use regular foreach.

0
source share

All Articles