How to use Use List<T>.RemoveAll to simplify for loop and remove items from collection

I have this implementation below. It uses a for loop. Is there a way to eliminate the for loop and simplify the code using C# List Extensions?

public class Member
{
    public string member { get; set; }
}

public class PatternMatch
{
    public static List<Member> Remove()
    {
        var prefix = new string[] { "usa-", "o-", "a-" };

        var members = new List<Member>();
        members.Add(new Member { member = "a-o@b.com" });
        members.Add(new Member { member = "usa-b@d.com" });
        members.Add(new Member { member = "c@d.com" });

        // don't use foreach since we will be modifying the collection 
        for (var i = members.Count - 1; i >= 0; i--)
        {
            foreach (var pattern in prefix)
            {
                if (members[i].member.StartsWith(pattern, StringComparison.InvariantCultureIgnoreCase))
                {
                    members.RemoveAt(i);
                }
            }
        }

        return members;
    }
}

>Solution :

RemoveAll implementation could look like this

members.RemoveAll(x => prefix.Any(p => x.member.StartsWith(p, StringComparison.InvariantCultureIgnoreCase)))

RemoveAll removes every item that matches the given Predicate<T>.

A Predicate<T> is very basically a method with a parameter of T and a return type of bool.

So the above code could be re-written as

members.RemoveAll(ConditionToRemove);
bool ConditionToRemove(Member x) => true;

The condition

x => prefix.Any(p => x.member.StartsWith(p, StringComparison.InvariantCultureIgnoreCase))

Does the following

for every T – I declared it as the variable x – it will check if their is Any entry in the list prefix that has the condition of

x.member.StartsWith(p, StringComparison.InvariantCultureIgnoreCase)

So, prefix.Any will return true if there is atleast one entry x.member starts with.

Leave a Reply