1

Instead of doing this horrible loop which does achieve the desired result :

foreach (var mealsViewModel in mealsListCollection) { foreach (var VARIABLE in mealsViewModel.Items) { foreach (var d in VARIABLE.ArticlesAvailable) { d.ArticleQty = 0; } } } 

I'm trying to achieve the same result but with this linQ statement :

mealsListCollection.ForEach(u => u.Items.Select(o => o.ArticlesAvailable.Select(c => { c.ArticleQty = 0; return c; }))); 

But the linQ statement does not reset ArticleQty to zero

What I am doing wrong? and why ?

3
  • because Select() method does not iterate over collection Commented Jun 25, 2018 at 4:26
  • you need somethig like this: mealsListCollection.ForEach(u => u.Items.ForEach(i => i.ArticlesAvailable.ForEach(c => c.ArticleQty = 0))) Commented Jun 25, 2018 at 4:29
  • Use MoreLinq's ForEach - github.com/morelinq/MoreLINQ/blob/master/MoreLinq/ForEach.cs - instead of Select. Commented Jun 25, 2018 at 4:30

3 Answers 3

1

Change your linq to ForEach cause Select does not iterate through collection in the way you want. MSDN definition:-

Select Projects each element of a sequence into a new form.

ForEach Performs the specified action on each element of the List.

mealsListCollection.ForEach(u => u.Items.ForEach(o => o.ArticlesAvailable.ForEach(c => { c.ArticleQty = 0; }))); 
Sign up to request clarification or add additional context in comments.

Comments

0

Use SelectMany to work through trees of nested lists. Use the ForEach function last to do the work:

mealsListCollection .SelectMany(m => m.Items) .SelectMany(i => i.ArticlesAvailable) .ToList() .ForEach(a => { a.ArticleQty = 0; }); 

1 Comment

ForEach() is an extension method for List<T>, not for Enumerable<T>. So you have to call ToList() right before ForEach().
0

What you are doing wrong is: select is returning your same collection, but has no effect until the objects are iterated over. Sitting in the foreach call, the selects are outside of the execution path. (Review comments for more information).

.select() in a call by itself does nothing special but determine what the returned list will look like. .select().ToList() iterates over the collection, applying the projection.

If you were to set a variable equal to the .select call, but never access the data inside it, then the values would essentially still be what they started as. As soon as you iterate over, or select a specific element, it would then apply the projections.

Changing the selects to foreachs per vasily's comments will give you the desired results.

Can I perhaps suggest that you look to set the value equal to 0 further up your stack ( or down)? - Without knowing your use case, maybe there Is a better place to default it back to 0 than where you have chosen? (automapper, Initializer, etc )

12 Comments

This is totally worng. Select() is not creating anything. More of that, where do you see, that OP is creating "a new obect with the 0 property"? There is a ToList() method, that actually create a new List of the same objects (for reference type).
Checkout the microsoft docs at the link provided below. Although I am using the word create, which it looks like you do not approve of, it is satisfying the return type of the select statement that OP is calling. There is, above, a new answer where the owner points out that this is infact a projection, which is described in the below link as well. Yes, you are correct in that op is not calling .ToList(), good call out. Thank you for that. msdn.microsoft.com/en-us/library/bb548891(v=vs.110).aspx
add to previous comment: collection.Select(i => i.Value = 0).ToList(); will actually change collection items, eventhough I not assign it to any variable. The same result will be with collection.Select(i => i.Value = 0).GetEnumerator(); and foreach(var item in collection.Select(i => i.Value = 0));.
Return type of ForEach() is void, so about which statement do you talk? And no, collection.Select(x => new { prop1 = "new prop" }); will not create any new collection or anything within existing collection. If you not iterate this, projection function code (x => new { prop1 = "new prop" }) will never be executed. But when you iterate this with, for example, ToList() call it his responsability to invoke projection function on every element in collection and build a list from results. It's how deferred execution works.
I still can't understand what you mean by "on the same page", but your answer is not misleading now, so I removed my downvote. Thanks for discussion, and I hope I was not too offencing (I did not mean to be rude at all).
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.