views:

280

answers:

3

I'm working on a Silverlight 2/3 application. I would like to use List.RemoveAll (or maybe it's IList.RemoveAll?) and specify a predicate so that I can remove a bunch of elements from a list in one sweep.

It seems like this function doesn't exist in Silverlight, though. Am I missing something here? Is there an alternative approach that's equally easy? Right now, I'm manually iterating over my elements in a foreach and keeping a second list (because you can't delete while iterating), and it's quite ... cumbersome.

+2  A: 

You can use LINQ like:

list = list.Where(predicate).ToList();

The alternative approach is to remove the elements in a for loop:

for (int i = list.Count - 1; i >= 0; --i)
    if (predicate(list[i])) 
         list.RemoveAt(i);
Mehrdad Afshari
I get a compilation error similar to: System.Collections.Generic.IList<T>' does not contain a definition for 'Where' and no extension method 'Where' ...
ashes999
@ashes999: Make sure there's a `using System.Linq;` on top of your source file. Also, make sure `System.Core` is referenced in your project. I tested it in Silverlight 3 and it should work.
Mehrdad Afshari
Precisely the solution I wanted -- using System.Linq!
ashes999
+1  A: 

If what you really need is access to the subset, then there's really no reason to do the remove, just access the subset like this:

Instead of (potentially:

List<string> subSet = l.RemoveAll ( p => !p.StartsWith ("a") );

Just get the inverse:

List<string> l = new List<string> () { "a", "b", "aa", "ab" };
var subSet = l.Where ( p => p.StartsWith ( "a" ) );


OK but to really remove them (assuming the same starting list as above):

l.Where ( p => p.StartsWith ( "a" ) ).ToList ().ForEach ( q => l.Remove ( q ) );

.Where is an extension method on IEnumerable, in System.Linq. So as long as your list is a generic IEnumerable (and you've added the using) it should be available.

Bobby
This is precisely the problem; l.RemoveAll and l.Where do not exist and throw compilation errors. This is what I'm trying to resolve...And I really *do* need to remove them :)
ashes999
those definitely do exist, the last code fragment will do it, I compiled and ran this in a Silverlight app before writing this :)
Bobby
It is annoying that they dropped the RemoveAll though, I suppose to help slim down the client Framework.
Bobby
Very useful -- close to the solution I used. But ultimately, I was trying to resolve the syntax error as to why Linq didn't work.
ashes999
A: 

I'm with Mehrdad on this, an extension method does the trick. To give you the full signature, here it is:

    /// <summary>
    /// Removes all entries from a target list where the predicate is true.
    /// </summary>
    /// <typeparam name="T">The type of item that must exist in the list.</typeparam>
    /// <param name="list">The list to remove entries from</param>
    /// <param name="predicate">The predicate that contains a testing criteria to determine if an entry should be removed from the list.</param>
    /// <returns>The number of records removed.</returns>
    public static int RemoveAll<T>(this IList<T> list, Predicate<T> predicate)
    {
        int returnCount = 0;

        for (int i = list.Count - 1; i >= 0; --i)
        {
            if (predicate(list[i]))
            {
                list.RemoveAt(i);
                returnCount++;
            }
        }

        return returnCount;
    }
absolutdeno