2

From what I understand, this seems to not be a safe practice...

I have a foreach loop on my list object that I am stepping through. Inside that foreach loop I am looking up records by an Id. Once I have that new list of records returned by that Id I do some parsing and add them to a new list.

What I would like to do is not step through the same Id more than once. So my thought process would be to remove it from the original list. However, this causes an error... and I understand why.

My question is... Is there a safe way to go about this? or should I restructure my thought process a bit? I was wondering if anyone had any experience or thoughts on how to solve this issue?

Here is a little pseudocode:

_myList.ForEach(x => 
{
    List<MyModel> newMyList = _myList.FindAll(y => y.SomeId == x.SomeId).ToList();

    //Here is where I would do some work with newMyList

    //Now I am done... time to remove all records with x.SomeId
    _myList.RemoveAll(y => y.SomeId == x.SomeId);
});

I know that _myList.RemoveAll(y => y.SomeId == x.SomeId); is wrong, but in theory that would kinda be what I would be looking for.

I have also toyed around with the idea of pushing the used SomeId to an idList and then have it check each time, but that seems cumbersome and was wondering if there was a nicer way to handle what I am looking to do.

Sorry if i didnt explain this that well. If there are any questions, please feel free to comment and I will answer/make edits where needed.

4
  • 2
    Why not using GroupBy? You can group your records by SomeId and then cycle on those groups Commented Jul 15, 2015 at 17:15
  • This may be possible. I would have to try and see if this would work for me. Thanks for the input! Commented Jul 15, 2015 at 17:18
  • Sorry deleted my answer. I see you mentioned maintaining a list of IDs in your question. GroupBy is much easier then maintaining a list of IDs. Commented Jul 15, 2015 at 17:30
  • 1
    @SebastianoRoncato - Thank you, this did in fact work for me. If you would like to post as an answer I would be happy to mark it as correct. Commented Jul 15, 2015 at 17:47

2 Answers 2

3

First off, using ForEach in your example isn't a great idea for these reasons.

You're right to think there are performance downsides to iterating through the full list for each remaining SomeId, but even making the list smaller every time would still require another full iteration of that subset (if it even worked).

As was pointed out in the comments, GroupBy on SomeId organizes the elements into groupings for you, and allows you to efficiently step through each subset for a given SomeId, like so:

_myList.GroupBy(x => x.SomeId)
       .Select(g => DoSomethingWithGroupedElements(g));

Jon Skeet has an excellent set of articles about how the Linq extensions could be implemented. I highly recommend checking it out for a better understanding of why this would be more efficient.

Sign up to request clarification or add additional context in comments.

Comments

1

First of all, a list inside a foreach is immutable, you can't add or delete content, nor rewrite an element. There are a few ways you could handle this situation:

GroupBy

This is the method I would use. You can group your list by the property you want, and iterate through the IGrouping formed this way

var groups = list.GroupBy(x => x.yourProperty);
foreach(var group in groups)
{
//your code
}

Distinct properties list

You could also save properties in another list, and cycle through that list instead of the original one

var propsList = list.Select(x=>x.yourProperty).Distinct();
foreach(var prop in propsList)
{
    var tmpList = list.Where(x=>x.yourProperty == prop);
    //your code
}

While loop

This will actually do what you originally wanted, but performances may not be optimal

while(list.Any())
{
    var prop = list.First().yourProperty;
    var tmpList = list.Where(x=>x.yourProperty == prop);
    //your code
    list.RemoveAll(x=>x.yourProperty == prop);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.