I want to do something like this:
List<SomeClass> list1 = ... List<SomeClass> list2 = ... Predicate<SomeClass> condition = ... ... list2.RemoveAll (!condition); ... list2.AddRange (list1.FindAll (condition));
However, this results in a compiler error, as !
can't be applied to Predicate<SomeClass>
. Is there any way to do this?
To negate a sequence of nested quantifiers, you flip each quantifier in the sequence and then negate the predicate. So the negation of ∀x ∃y : P(x, y) is ∃x ∀y : P(x, y) and So the negation of ∃x ∀y : P(x, y) and ∀x ∃y : P(x, y).
1 Predicate negation: negative and opposite predicates. Negation in logic is an operator reversing truth- or semantic-values. In natural language negation turns an affirmative sentence into its denial.
Predicate negate() Method The Predicate. negate() method returns the logical negation of an existing predicate. Predicate<Integer> isEven = i -> i % 2 == 0; Predicate<Integer> isOdd = isEven.
You could use a lambda expression to define an anonymous delegate inplace that is the result of negating the result of the predicate:
list.RemoveAll(x => !condition(x));
Another option:
static Predicate<T> Negate<T>(Predicate<T> predicate) { return x => !predicate(x); }
Usage:
// list is List<T> some T // predicate is Predicate<T> some T list.RemoveAll(Negate(predicate));
The reason that list.RemoveAll(!condition)
does not work is that there is no !
operator defined on delegates. This is why you must define a new delegate in terms of condition
as shown above.
This is actually possible, but maybe in a slightly different form than you're used to. In .NET, lambda expressions can either be interpreted as delegates OR as expression trees. It is relatively straightforward to perform a NOT
operation on an expression tree.
Here is a sample using your code as a starting point:
namespace Sample { using System; using System.Collections.Generic; using System.Linq.Expressions; internal class ExpressionSample { private static Expression<TDelegate> Negate<TDelegate>(Expression<TDelegate> expression) { return Expression.Lambda<TDelegate>(Expression.Not(expression.Body), expression.Parameters); } private static void Main() { // Match any string of length 2 or more characters Expression<Predicate<string>> expression = (s) => s.Length > 1; // Logical negation, i.e. match string of length 1 or fewer characters Expression<Predicate<string>> negatedExpression = ExpressionSample.Negate(expression); // Compile expressions to predicates Predicate<string> predicate = expression.Compile(); Predicate<string> negativePredicate = negatedExpression.Compile(); List<string> list1 = new List<string> { string.Empty, "an item", "x", "another item" }; List<string> list2 = new List<string> { "yet another item", "still another item", "y", string.Empty }; list2.RemoveAll(negativePredicate); list2.AddRange(list1.FindAll(predicate)); list2.ForEach((s) => Console.WriteLine(s)); } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With