599

I am looking for a better pattern for working with a list of elements which each need processed and then depending on the outcome are removed from the list.

You can't use .Remove(element) inside a foreach (var element in X) (because it results in Collection was modified; enumeration operation may not execute. exception)... you also can't use for (int i = 0; i < elements.Count(); i++) and .RemoveAt(i) because it disrupts your current position in the collection relative to i.

Is there an elegant way to do this?

Vikrant
  • 4,920
  • 17
  • 48
  • 72
InvertedAcceleration
  • 10,695
  • 9
  • 46
  • 71

28 Answers28

944

Iterate your list in reverse with a for loop:

for (int i = safePendingList.Count - 1; i >= 0; i--)
{
    // some code
    // safePendingList.RemoveAt(i);
}

Example:

var list = new List<int>(Enumerable.Range(1, 10));
for (int i = list.Count - 1; i >= 0; i--)
{
    if (list[i] > 5)
        list.RemoveAt(i);
}
list.ForEach(i => Console.WriteLine(i));

Alternately, you can use the RemoveAll method with a predicate to test against:

safePendingList.RemoveAll(item => item.Value == someValue);

Here's a simplified example to demonstrate:

var list = new List<int>(Enumerable.Range(1, 10));
Console.WriteLine("Before:");
list.ForEach(i => Console.WriteLine(i));
list.RemoveAll(i => i > 5);
Console.WriteLine("After:");
list.ForEach(i => Console.WriteLine(i));
Ahmad Mageed
  • 94,561
  • 19
  • 163
  • 174
  • 25
    For those coming from Java, C#'s List is like ArrayList in that insertion/removal is O(n) and retrieval via an index is O(1). This is *not* a traditional linked list. It seems a bit unfortunate C# uses the word "List" to describe this data structure since it brings to mind the classic linked list. – sleep Dec 19 '13 at 23:55
  • 117
    Nothing in the name 'List' says 'LinkedList'. People coming from other languages than Java might be confused when it would be a linked list. – GolezTrol May 01 '14 at 14:13
  • 5
    I ended up here through a vb.net search so in case anyone wants the vb.net equivalent syntax for RemoveAll: `list.RemoveAll(Function(item) item.Value = somevalue)` – pseudocoder Nov 06 '14 at 17:35
  • 1
    This also works in Java with minimal modification: `.size()` instead of `.Count` and `.remove(i)` instead of `.removeAt(i)`. Clever--thanks! – Autumn Leonard Dec 11 '15 at 15:17
  • 5
    I made a little test for performance and it turned out that `RemoveAll()` takes three times as much time as the backwards `for` loop. So I am definitely sticking with the loop, at least in sections where it matters. – Crusha K. Rool Nov 15 '16 at 01:40
  • 1
    @AutumnLeonard A better solution for Java would be using the `Iterator` (assuming the `remove()` method is implemented). – ndm13 Sep 20 '17 at 14:53
  • 1
    @JarrodSmith, it's worth noting that with lists less than massive size, modern hardware architecture gives a massive performance benefit to arrays such that for most practical purposes outside very large data sets (or lists of very large contiguous structures; i.e. non-references, which aren't a Java feature) and some other edge cases, despite the illusion granted by big-O complexity analysis (this is mostly due to processor-localized caching and prefetching). One of many articles on the subject: https://youthdev.net/en/performance-of-array-vs-linked-list-on-modern-computers/ – TheXenocide Mar 15 '18 at 13:41
  • I am, admittedly, rather late to the discussion lol. I also didn't give that article a thorough read as I was only looking for an example of something I've already studied, though it looked relevant enough – TheXenocide Mar 15 '18 at 13:42
  • Is there any reason WHY `.RemoveAll()` is safe, while `.Remove()` is not?! Surely `.RemoveAll()` is also modifying the collection. – nl-x Mar 06 '20 at 11:15
  • 2
    @nl-x The difference is when you use it. Using `.Remove()` on the same collection you are iterating over, with a `foreach` is where this error comes up. Using `RemoveAt(...)` while using a `for` loop in reverse lets us remove an element while we keep track of the index to avoid going out of range. And when using `RemoveAll()` it wouldn't be used in a loop, so there's no concern of modifying the collection itself since we aren't iterating over it. – Ahmad Mageed Mar 30 '20 at 00:16
178
 foreach (var item in list.ToList()) {
     list.Remove(item);
 }

If you add ".ToList()" to your list (or the results of a LINQ query), you can remove "item" directly from "list" without the dreaded "Collection was modified; enumeration operation may not execute." error. The compiler makes a copy of "list", so that you can safely do the remove on the array.

While this pattern is not super efficient, it has a natural feel and is flexible enough for almost any situation. Such as when you want to save each "item" to a DB and remove it from the list only when the DB save succeeds.

Greg Little
  • 3,360
  • 2
  • 19
  • 16
  • 22
    This is the best solution if efficiency is not crucial. – IvanP Jun 02 '16 at 11:54
  • 2
    this is faster and more readable too: list.RemoveAll(i => true); – santiago arizti Jul 07 '16 at 00:42
  • 4
    @Greg Little , did I understand you correctly - when you add ToList() compiler goes through copied collection but removes from original? – Pyrejkee Jan 17 '19 at 10:56
  • If your list contains duplicate items and you only want to remove the item occurring later in the list then won't this remove the wrong item? – Tim MB Feb 11 '20 at 16:56
  • 1
    @Pyrejkee yes, that's because if you iterated through the original list, when you removed an item it would give an error saying the collection was modified so the foreach loop would crash. With a copy of the list, items are not removed from the copy but only from the original list, thus allowing the loop to complete and the original list to be modified – NiallMitch14 Aug 14 '20 at 10:40
  • @TimMB If that is the case, this is not the way to do it, regardless of `ToList`. That is a different question. – NetMage Feb 11 '21 at 19:04
  • Thanks for sharing, this is what I was looking for. – user2217057 Mar 08 '21 at 07:10
  • Genius. Never would have guessed that. – Brian Aug 11 '21 at 21:56
  • If the list is huge this doubles the risk of an OutOfMemoryException for no reason. If `list` is actually a LINQ-query this approach can cause a horrible performance since it needs to execute it twice. – Tim Schmelter Nov 10 '22 at 09:08
99

A simple and straightforward solution:

Use a standard for-loop running backwards on your collection and RemoveAt(i) to remove elements.

shA.t
  • 16,580
  • 5
  • 54
  • 111
  • 9
    Be aware that removing items one at a time is *not* efficient if your list contains many items. It has the potential to be O(n^2). Imagine a List with two billion items where it just happens that the first billion items all end up being deleted. Each removal forces all later items to be copied, so you end up copying a billion items a billion times each. This isn't because of the reverse iteration, it is because of the one-at-a-time removal. RemoveAll ensures that each item is copied at most once so it is linear. One-at-a-time removal may be a billion times slower. O(n) versus O(n^2). – Bruce Dawson Jul 08 '19 at 03:57
  • @BruceDawson, is this conclusion based on observation on RemoveAll internals? – AaA Jun 06 '21 at 08:24
  • @AaA - my observation is not based on looking at the RemoveAll internals but from my understanding of how a C# list is implemented. It is just an array of items and removing a single item necessarily requires shifting all items afterwards down one position. Therefore the algorithm suggested here will have O(n^2) performance. This is unnecessary. There are simple algorithms that can do this task in O(n) time, potentially millions of times faster. I believe that remove_if is the correct function. It copies each item once, instead of up to n times. – Bruce Dawson Jun 11 '21 at 00:29
  • @BruceDawson if it's not efficient to remove one at a time with a list, is there any other collection that can be used instead? – BenKoshy Dec 12 '22 at 02:28
  • You could use a different type of collection (a linked list) to avoid this, but I think that would be the wrong solution. The correct solution is to use the right algorithm. .RemoveAll with a predicate will efficiently remove items. It is written such that each item is only touched (removed or moved) once. – Bruce Dawson Dec 13 '22 at 21:26
81

Reverse iteration should be the first thing to come to mind when you want to remove elements from a Collection while iterating over it.

Luckily, there is a more elegant solution than writing a for loop which involves needless typing and can be error prone.

ICollection<int> test = new List<int>(new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10});

foreach (int myInt in test.Reverse<int>())
{
    if (myInt % 2 == 0)
    {
        test.Remove(myInt);
    }
}
jedesah
  • 2,983
  • 2
  • 17
  • 29
  • 7
    This worked perfectly for me. Simple, and elegant, and required minimal changes to my code. – Stephen MacDougall Jul 22 '13 at 17:58
  • 1
    Is this is just flippin genius? And I agree with @StephenMacDougall , I do not need to use those C++'y for loops and just get on with LINQ as intended. – Piotr Kula Apr 29 '14 at 10:07
  • 8
    I don't see any advantage over simple foreach (int myInt in test.ToList()) { if (myInt % 2 == 0) { test.Remove(myInt); } } You still have to allocate a copy for Reverse and it introduces Huh? moment - why is there Reverse. – jahav May 25 '15 at 13:38
  • @jahav The `Reverse()` is in order for the iterator to go through the list backwards. If you don't do that, your indexes get screwed up because you are removing elements from the list at the same time (so every element after the removed element's index goes down by one). Since the indexes of the elements before the removed element do not change, by iterating in the reverse order, you are safe against the awful consequences of your own mutations. Btw, this was a long time ago, today I would suggest that if at all possible, you use a language such as Haskell and avoid mutation altogether. – jedesah Jun 17 '15 at 00:43
  • 20
    @jedesah Yes, `Reverse()` creates an iterator that goes through list backwards, but it **allocates extra buffer** with same size as the list itself for it ( http://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,792 ). `Reverse` doesn't just go through the original list in reverse order (w/o allocating extra memory). Therefore both `ToList()` and `Reverse()` have same memory consumption (both create copy), but `ToList()` doesn't do anything to the data. With `Reverse()`, I would wonder why is list reversed, for what reason. – jahav Jun 17 '15 at 09:00
  • 1
    @jahav I see your point. That is quite disappointing that the implementation of `Reverse()` creates a new buffer, I am not quite sure I understand why that is necessary. It seems to me that depending on the underlying structure of the `Enumerable`, it should at least in some cases be possible to achieve reverse iteration without allocating linear memory. – jedesah Jun 17 '15 at 17:59
  • memory shmemory. this is by far the most ellegant solution – Squibly Jun 13 '21 at 12:10
  • This can cause a wrong result. For example: you want to remove duplicates from a list but the first one should survive, this will reverse the items so the last duplicate will survive. – Tim Schmelter Nov 10 '22 at 09:12
27

Using the ToArray() on a generic list allows you to do a Remove(item) on your generic List:

        List<String> strings = new List<string>() { "a", "b", "c", "d" };
        foreach (string s in strings.ToArray())
        {
            if (s == "b")
                strings.Remove(s);
        }
  • 3
    This isn't wrong but I have to point out that this bypasses the need to create a 2nd "storage" list of the items you want removed at the expense of copying the entire list to an array. A 2nd list of hand-picked elements will probably have less items. – Ahmad Mageed Oct 17 '09 at 15:06
27

Select the elements you do want rather than trying to remove the elements you don't want. This is so much easier (and generally more efficient too) than removing elements.

var newSequence = (from el in list
                   where el.Something || el.AnotherThing < 0
                   select el);

I wanted to post this as a comment in response to the comment left by Michael Dillon below, but it's too long and probably useful to have in my answer anyway:

Personally, I'd never remove items one-by-one, if you do need removal, then call RemoveAll which takes a predicate and only rearranges the internal array once, whereas Remove does an Array.Copy operation for every element you remove. RemoveAll is vastly more efficient.

And when you're backwards iterating over a list, you already have the index of the element you want to remove, so it would be far more efficient to call RemoveAt, because Remove first does a traversal of the list to find the index of the element you're trying to remove, but you already know that index.

So all in all, I don't see any reason to ever call Remove in a for-loop. And ideally, if it is at all possible, use the above code to stream elements from the list as needed so no second data structure has to be created at all.

JulianR
  • 16,213
  • 5
  • 55
  • 85
26

Using .ToList() will make a copy of your list, as explained in this question: ToList()-- Does it Create a New List?

By using ToList(), you can remove from your original list, because you're actually iterating over a copy.

foreach (var item in listTracked.ToList()) {    

        if (DetermineIfRequiresRemoval(item)) {
            listTracked.Remove(item)
        }

     }
Community
  • 1
  • 1
StuartQ
  • 3,739
  • 1
  • 26
  • 23
  • 2
    But from a performance point of view you are copying your list, which may take some time. Good and easy way to do it, but with a not so good performance – Florian K Mar 13 '17 at 15:08
19

If the function that determines which items to delete has no side effects and doesn't mutate the item (it's a pure function), a simple and efficient (linear time) solution is:

list.RemoveAll(condition);

If there are side effects, I'd use something like:

var toRemove = new HashSet<T>();
foreach(var item in items)
{
     ...
     if(condition)
          toRemove.Add(item);
}
items.RemoveAll(toRemove.Contains);

This is still linear time, assuming the hash is good. But it has an increased memory use due to the hashset.

Finally if your list is only an IList<T> instead of a List<T> I suggest my answer to How can I do this special foreach iterator?. This will have linear runtime given typical implementations of IList<T>, compared with quadratic runtime of many other answers.

Community
  • 1
  • 1
CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
14

As any remove is taken on a condition you can use

list.RemoveAll(item => item.Value == someValue);
Ahmad
  • 8,811
  • 11
  • 76
  • 141
10
List<T> TheList = new List<T>();

TheList.FindAll(element => element.Satisfies(Condition)).ForEach(element => TheList.Remove(element));
Burhan Khalid
  • 169,990
  • 18
  • 245
  • 284
Mauricio Ramalho
  • 849
  • 1
  • 8
  • 15
10

You can't use foreach, but you could iterate forwards and manage your loop index variable when you remove an item, like so:

for (int i = 0; i < elements.Count; i++)
{
    if (<condition>)
    {
        // Decrement the loop counter to iterate this index again, since later elements will get moved down during the remove operation.
        elements.RemoveAt(i--);
    }
}

Note that in general all of these techniques rely on the behaviour of the collection being iterated. The technique shown here will work with the standard List(T). (It is quite possible to write your own collection class and iterator that does allow item removal during a foreach loop.)

yoyo
  • 8,310
  • 4
  • 56
  • 50
8

For loops are a bad construct for this.

Using while

var numbers = new List<int>(Enumerable.Range(1, 3));

while (numbers.Count > 0)
{
    numbers.RemoveAt(0);
}

But, if you absolutely must use for

var numbers = new List<int>(Enumerable.Range(1, 3));

for (; numbers.Count > 0;)
{
    numbers.RemoveAt(0);
}

Or, this:

public static class Extensions
{

    public static IList<T> Remove<T>(
        this IList<T> numbers,
        Func<T, bool> predicate)
    {
        numbers.ForEachBackwards(predicate, (n, index) => numbers.RemoveAt(index));
        return numbers;
    }

    public static void ForEachBackwards<T>(
        this IList<T> numbers,
        Func<T, bool> predicate,
        Action<T, int> action)
    {
        for (var i = numbers.Count - 1; i >= 0; i--)
        {
            if (predicate(numbers[i]))
            {
                action(numbers[i], i);
            }
        }
    }
}

Usage:

var numbers = new List<int>(Enumerable.Range(1, 10)).Remove((n) => n > 5);

However, LINQ already has RemoveAll() to do this

var numbers = new List<int>(Enumerable.Range(1, 10));
numbers.RemoveAll((n) => n > 5);

Lastly, you are probably better off using LINQ's Where() to filter and create a new list instead of mutating the existing list. Immutability is usually good.

var numbers = new List<int>(Enumerable.Range(1, 10))
    .Where((n) => n <= 5)
    .ToList();
Christian Findlay
  • 6,770
  • 5
  • 51
  • 103
6

Using Remove or RemoveAt on a list while iterating over that list has intentionally been made difficult, because it is almost always the wrong thing to do. You might be able to get it working with some clever trick, but it would be extremely slow. Every time you call Remove it has to scan through the entire list to find the element you want to remove. Every time you call RemoveAt it has to move subsequent elements 1 position to the left. As such, any solution using Remove or RemoveAt, would require quadratic time, O(n²).

Use RemoveAll if you can. Otherwise, the following pattern will filter the list in-place in linear time, O(n).

// Create a list to be filtered
IList<int> elements = new List<int>(new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
// Filter the list
int kept = 0;
for (int i = 0; i < elements.Count; i++) {
    // Test whether this is an element that we want to keep.
    if (elements[i] % 3 > 0) {
        // Add it to the list of kept elements.
        elements[kept] = elements[i];
        kept++;
    }
}
// Unfortunately IList has no Resize method. So instead we
// remove the last element of the list until: elements.Count == kept.
while (kept < elements.Count) elements.RemoveAt(elements.Count-1);
bcmpinc
  • 3,202
  • 29
  • 36
6

The best way to remove items from a list while iterating over it is to use RemoveAll(). But the main concern written by people is that they have to do some complex things inside the loop and/or have complex compare cases.

The solution is to still use RemoveAll() but use this notation:

var list = new List<int>(Enumerable.Range(1, 10));
list.RemoveAll(item => 
{
    // Do some complex operations here
    // Or even some operations on the items
    SomeFunction(item);
    // In the end return true if the item is to be removed. False otherwise
    return item > 5;
});
Huseyin Yagli
  • 9,896
  • 6
  • 41
  • 50
5

I would reassign the list from a LINQ query that filtered out the elements you didn't want to keep.

list = list.Where(item => ...).ToList();

Unless the list is very large there should be no significant performance problems in doing this.

Martin Liversage
  • 104,481
  • 22
  • 209
  • 256
4

By assuming that predicate is a Boolean property of an element, that if it is true, then the element should be removed:

        int i = 0;
        while (i < list.Count())
        {
            if (list[i].predicate == true)
            {
                list.RemoveAt(i);
                continue;
            }
            i++;
        }
roeesha
  • 86
  • 2
  • I gave this an upvote as sometimes it could be more efficient to move through the List in order (not reverse order). Perhaps you could stop when finding the first item not to remove because the list is ordered. (Imagine a 'break' where the i++ is in this example. – FrankKrumnow Feb 01 '18 at 11:06
4

In C# one easy way is to mark the ones you wish to delete then create a new list to iterate over...

foreach(var item in list.ToList()){if(item.Delete) list.Remove(item);}  

or even simpler use linq....

list.RemoveAll(p=>p.Delete);

but it is worth considering if other tasks or threads will have access to the same list at the same time you are busy removing, and maybe use a ConcurrentList instead.

andrew pate
  • 3,833
  • 36
  • 28
2

I wish the "pattern" was something like this:

foreach( thing in thingpile )
{
    if( /* condition#1 */ )
    {
        foreach.markfordeleting( thing );
    }
    elseif( /* condition#2 */ )
    {
        foreach.markforkeeping( thing );
    }
} 
foreachcompleted
{
    // then the programmer's choices would be:

    // delete everything that was marked for deleting
    foreach.deletenow(thingpile); 

    // ...or... keep only things that were marked for keeping
    foreach.keepnow(thingpile);

    // ...or even... make a new list of the unmarked items
    others = foreach.unmarked(thingpile);   
}

This would align the code with the process that goes on in the programmer's brain.

warrens
  • 1,661
  • 18
  • 16
  • 1
    Easy enough. Just create a boolean flag array (use a 3-state type, e.g. `Nullable`, if you want to allow unmarked), then use it after the foreach to remove/keep items. – Dan Bechard Jul 17 '14 at 13:50
2
foreach(var item in list.ToList())

{

if(item.Delete) list.Remove(item);

}

Simply create an entirely new list from the first one. I say "Easy" rather than "Right" as creating an entirely new list probably comes at a performance premium over the previous method (I haven't bothered with any benchmarking.) I generally prefer this pattern, it can also be useful in overcoming Linq-To-Entities limitations.

for(i = list.Count()-1;i>=0;i--)

{

item=list[i];

if (item.Delete) list.Remove(item);

}

This way cycles through the list backwards with a plain old For loop. Doing this forwards could be problematic if the size of the collection changes, but backwards should always be safe.

Lijo
  • 6,498
  • 5
  • 49
  • 60
2

Just wanted to add my 2 cents to this in case this helps anyone, I had a similar problem but needed to remove multiple elements from an array list while it was being iterated over. the highest upvoted answer did it for me for the most part until I ran into errors and realized that the index was greater than the size of the array list in some instances because multiple elements were being removed but the index of the loop didn't keep track of that. I fixed this with a simple check:

ArrayList place_holder = new ArrayList();
place_holder.Add("1");
place_holder.Add("2");
place_holder.Add("3");
place_holder.Add("4");

for(int i = place_holder.Count-1; i>= 0; i--){
    if(i>= place_holder.Count){
        i = place_holder.Count-1; 
    }

// some method that removes multiple elements here
}
Sasha1296
  • 149
  • 2
  • 8
2

There is an option that hasn't been mentioned here.

If you don't mind adding a bit of code somewhere in your project, you can add and extension to List to return an instance of a class that does iterate through the list in reverse.

You would use it like this :

foreach (var elem in list.AsReverse())
{
    //Do stuff with elem
    //list.Remove(elem); //Delete it if you want
}

And here is what the extension looks like:

public static class ReverseListExtension
{
    public static ReverseList<T> AsReverse<T>(this List<T> list) => new ReverseList<T>(list);

    public class ReverseList<T> : IEnumerable
    {
        List<T> list;
        public ReverseList(List<T> list){ this.list = list; }

        public IEnumerator GetEnumerator()
        {
            for (int i = list.Count - 1; i >= 0; i--)
                yield return list[i];
            yield break;
        }
    }
}

This is basically list.Reverse() without the allocation.

Like some have mentioned you still get the drawback of deleting elements one by one, and if your list is massively long some of the options here are better. But I think there is a world where someone would want the simplicity of list.Reverse(), without the memory overhead.

Garazbolg
  • 21
  • 1
1

Copy the list you are iterating. Then remove from the copy and interate the original. Going backwards is confusing and doesn't work well when looping in parallel.

var ids = new List<int> { 1, 2, 3, 4 };
var iterableIds = ids.ToList();

Parallel.ForEach(iterableIds, id =>
{
    ids.Remove(id);
});
1

I would do like this

using System.IO;
using System;
using System.Collections.Generic;

class Author
    {
        public string Firstname;
        public string Lastname;
        public int no;
    }

class Program
{
    private static bool isEven(int i) 
    { 
        return ((i % 2) == 0); 
    } 

    static void Main()
    {    
        var authorsList = new List<Author>()
        {
            new Author{ Firstname = "Bob", Lastname = "Smith", no = 2 },
            new Author{ Firstname = "Fred", Lastname = "Jones", no = 3 },
            new Author{ Firstname = "Brian", Lastname = "Brains", no = 4 },
            new Author{ Firstname = "Billy", Lastname = "TheKid", no = 1 }
        };

        authorsList.RemoveAll(item => isEven(item.no));

        foreach(var auth in authorsList)
        {
            Console.WriteLine(auth.Firstname + " " + auth.Lastname);
        }
    }
}

OUTPUT

Fred Jones
Billy TheKid
Gambitier
  • 504
  • 6
  • 18
0

I found myself in a similar situation where I had to remove every nth element in a given List<T>.

for (int i = 0, j = 0, n = 3; i < list.Count; i++)
{
    if ((j + 1) % n == 0) //Check current iteration is at the nth interval
    {
        list.RemoveAt(i);
        j++; //This extra addition is necessary. Without it j will wrap
             //down to zero, which will throw off our index.
    }
    j++; //This will always advance the j counter
}
Niko
  • 4,158
  • 9
  • 46
  • 85
0

The cost of removing an item from the list is proportional to the number of items following the one to be removed. In the case where the first half of the items qualify for removal, any approach which is based upon removing items individually will end up having to perform about N*N/4 item-copy operations, which can get very expensive if the list is large.

A faster approach is to scan through the list to find the first item to be removed (if any), and then from that point forward copy each item which should be retained to the spot where it belongs. Once this is done, if R items should be retained, the first R items in the list will be those R items, and all of the items requiring deletion will be at the end. If those items are deleted in reverse order, the system won't end up having to copy any of them, so if the list had N items of which R items, including all of the first F, were retained, it will be necessary to copy R-F items, and shrink the list by one item N-R times. All linear time.

supercat
  • 77,689
  • 9
  • 166
  • 211
0

My approach is that I first create a list of indices, which should get deleted. Afterwards I loop over the indices and remove the items from the initial list. This looks like this:

var messageList = ...;
// Restrict your list to certain criteria
var customMessageList = messageList.FindAll(m => m.UserId == someId);

if (customMessageList != null && customMessageList.Count > 0)
{
    // Create list with positions in origin list
    List<int> positionList = new List<int>();
    foreach (var message in customMessageList)
    {
        var position = messageList.FindIndex(m => m.MessageId == message.MessageId);
        if (position != -1)
            positionList.Add(position);
    }
    // To be able to remove the items in the origin list, we do it backwards
    // so that the order of indices stays the same
    positionList = positionList.OrderByDescending(p => p).ToList();
    foreach (var position in positionList)
    {
        messageList.RemoveAt(position);
    }
}
testing
  • 19,681
  • 50
  • 236
  • 417
-1

Trace the elements to be removed with a property, and remove them all after process.

using System.Linq;

List<MyProperty> _Group = new List<MyProperty>();
// ... add elements

bool cond = false;
foreach (MyProperty currObj in _Group)
{
    // here it is supposed that you decide the "remove conditions"...
    cond = true; // set true or false...
    if (cond) 
    {
        // SET - element can be deleted
        currObj.REMOVE_ME = true;
    }
}
// RESET
_Group.RemoveAll(r => r.REMOVE_ME);
-5
myList.RemoveAt(i--);

simples;
S.W.
  • 60
  • 6