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);
}
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
(ie, 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() );
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.