1

Suppose I have two lists of strings, List1 and list2, where List1 is a property of an object of type Foo in a list fooList.

I would like to remove a given Foo if no string in foo.List1 matches any string in list2 a la RemoveAll.

I can do this with nested for loops, but is there a way to do this with a single slick LINQ expression?

Long-winded code, building a new list rather than removing stuff from the existing list:

            var newFooList = new List<Foo>

            foreach (Foo f in fooList)
            {
                bool found = false;

                foreach (string s in newFooList)
                {
                    if (f.FooStringList.Contains(s))
                    {
                        found = true;
                        break;
                    }
                }

                if (found)
                    newFooList.Add(f);
            }
1
  • 1
    In my opinion you should include long-winded code as it would communicate your desired behaviour better than your description. Commented Oct 2, 2013 at 1:32

1 Answer 1

5

Yes:

var list2 = new List<string> { "one", "two", "four" };
var fooList = new List<Foo> {
    new Foo { List1 = new List<string> { "two", "three", "five" } },
    new Foo { List1 = new List<string> { "red", "blue" } }
};
fooList.RemoveAll( x => !x.List1.Intersect( list2 ).Any() );
Console.WriteLine( fooList );

Basically all the magic happens in RemoveAll: this only removes entries where the intersection of the entry's List1 property and list2 (i.e., the overlap) is empty.

I personally find the !....Any() construct kind of hard to read, so I like to have the following extension method on hand:

public static class Extensions {
    public static bool Empty<T>( this IEnumerable<T> l, 
            Func<T,bool> predicate=null ) {
        return predicate==null ? !l.Any() : !l.Any( predicate );
    }
}

Then I can re-write the magic line in a way that's a little clearer:

fooList.RemoveAll( x => x.List1.Intersect( list2 ).Empty() );
Sign up to request clarification or add additional context in comments.

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.