合并多个谓词
合并多个谓词
在C# .NET 2.0中,有没有办法将多个Predicate组合起来?假设我有以下代码:
Listnames = new List (); names.Add("Jacob"); names.Add("Emma"); names.Add("Michael"); names.Add("Isabella"); names.Add("Ethan"); names.Add("Emily"); List filteredNames = names.FindAll(StartsWithE); static bool StartsWithE(string s) { if (s.StartsWith("E")) { return true; } else { return false; } }
这给我返回了:
Emma Ethan Emily
这是非常酷的东西,但是我现在想要使用多个谓词进行过滤。所以我想要这样说:
ListfilteredNames = names.FindAll(StartsWithE OR StartsWithI);
以获得:
Emma Isabella Ethan Emily
我该如何实现这个?
目前我只是两次过滤完整的列表,然后将结果合并。但不幸的是,这相当低效,更重要的是,我丢失了原始的排序顺序,这在我的情况下是不可接受的。
我还需要能够迭代任意数量的过滤器/谓词,因为可能有很多个。
再次强调,这需要是一个.NET 2.0的解决方案,很遗憾我不能使用更新版本的框架。
非常感谢。
在这段代码中,我们看到了两个方法:Or和And。这些方法接受一个或多个Predicate
这种需求的原因可能是在某些情况下,我们需要使用多个谓词来进行判断或过滤。例如,在上述代码中,我们使用Or方法将StartsWithE和StartsWithI两个谓词组合起来,以便筛选出以字母E或I开头的字符串。
解决这个问题的方法是使用委托和循环来遍历每个谓词,并根据谓词的结果返回true或false。在Or方法中,只要有一个谓词返回true,就会返回true。而在And方法中,只要有一个谓词返回false,就会返回false。
另外,还提到了另一种解决方法,使用多播委托和GetInvocationList()方法来拆分委托,并执行相同的操作。这种方法使用起来更加简洁,但也被认为是对多播委托的滥用。
这些方法对于需要使用多个谓词来进行判断或过滤的情况非常有用。它们提供了一种简洁和灵活的方式来组合谓词,并使代码更加可读和易于维护。
在这段对话中,出现了一个问题:如何将多个谓词(predicates)组合在一起使用。谓词是一种函数类型,接受一个参数并返回一个布尔值。在这个问题中,需要将谓词`predicate1`和`predicate2`组合成一个新的谓词。
解决方法如下所示:
Func<string, bool> predicate1 = s => s.StartsWith("E"); Func<string, bool> predicate2 = s => s.StartsWith("I"); Func<string, bool> combinedOr = s => (predicate1(s) || predicate2(s)); Func<string, bool> combinedAnd = s => (predicate1(s) && predicate2(s));
以上代码定义了两个谓词`predicate1`和`predicate2`,分别用于判断字符串是否以"E"和"I"开头。然后,使用逻辑运算符`||`和`&&`将这两个谓词组合成了两个新的谓词`combinedOr`和`combinedAnd`。`combinedOr`返回一个字符串是否以"E"或"I"开头的布尔值,`combinedAnd`返回一个字符串是否同时以"E"和"I"开头的布尔值。
这种方法的优点是简单、清晰、直接,并且代码的可读性很高。
Combine Multiple Predicates是一个问题,它的出现原因是需要在一个列表中使用多个谓词进行筛选,并返回满足所有谓词的项。为了解决这个问题,可以扩展列表的FindAll方法,允许在列表中堆叠谓词。下面是一个示例代码:
public static class ExtensionMethods { public static ListFindAll (this List list, List > predicates) { List L = new List (); foreach (T item in list) { bool pass = true; foreach (Predicate p in predicates) { if (!(p(item))) { pass = false; break; } } if (pass) L.Add(item); } return L; } }
这个方法返回一个只包含满足所有给定谓词的项的列表。当然,这个方法也可以很容易地改为使用OR运算符来组合谓词。通过这个方法,可以组合多个逻辑条件。
下面是一个使用示例:
{ List> P = new List >(); P.Add(j => j > 100); P.Add(j => j % 5 == 0 || j % 7 == 0); P.Add(j => j < 1000); List L = new List () { 0, 1, 2, ... 999, 1000 }; List result = L.FindAll(P); // result将包含:105, 110, 112, 115, 119, 120, ... 994, 995 }
在使用者的评论中提到了一个bug,即第一个break语句导致即使一个谓词返回false,该项仍然会被添加到列表中。开发者对此做了修复,并感谢评论者的指正。
这是一个非常棒的解决方案,特别适用于动态创建任意数量的谓词。