合并多个谓词

11 浏览
0 Comments

合并多个谓词

在C# .NET 2.0中,有没有办法将多个Predicate组合起来?假设我有以下代码:

List names = 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

这是非常酷的东西,但是我现在想要使用多个谓词进行过滤。所以我想要这样说:

List filteredNames = names.FindAll(StartsWithE OR StartsWithI);

以获得:

Emma
Isabella
Ethan
Emily

我该如何实现这个?

目前我只是两次过滤完整的列表,然后将结果合并。但不幸的是,这相当低效,更重要的是,我丢失了原始的排序顺序,这在我的情况下是不可接受的。

我还需要能够迭代任意数量的过滤器/谓词,因为可能有很多个。

再次强调,这需要是一个.NET 2.0的解决方案,很遗憾我不能使用更新版本的框架。

非常感谢。

0
0 Comments

在这段代码中,我们看到了两个方法:Or和And。这些方法接受一个或多个Predicate的参数,并返回一个新的Predicate。这些方法的目的是将多个谓词组合成一个新的谓词,以便在使用它们时进行过滤或判断。

这种需求的原因可能是在某些情况下,我们需要使用多个谓词来进行判断或过滤。例如,在上述代码中,我们使用Or方法将StartsWithE和StartsWithI两个谓词组合起来,以便筛选出以字母E或I开头的字符串。

解决这个问题的方法是使用委托和循环来遍历每个谓词,并根据谓词的结果返回true或false。在Or方法中,只要有一个谓词返回true,就会返回true。而在And方法中,只要有一个谓词返回false,就会返回false。

另外,还提到了另一种解决方法,使用多播委托和GetInvocationList()方法来拆分委托,并执行相同的操作。这种方法使用起来更加简洁,但也被认为是对多播委托的滥用。

这些方法对于需要使用多个谓词来进行判断或过滤的情况非常有用。它们提供了一种简洁和灵活的方式来组合谓词,并使代码更加可读和易于维护。

0
0 Comments

在这段对话中,出现了一个问题:如何将多个谓词(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"开头的布尔值。

这种方法的优点是简单、清晰、直接,并且代码的可读性很高。

0
0 Comments

Combine Multiple Predicates是一个问题,它的出现原因是需要在一个列表中使用多个谓词进行筛选,并返回满足所有谓词的项。为了解决这个问题,可以扩展列表的FindAll方法,允许在列表中堆叠谓词。下面是一个示例代码:

public static class ExtensionMethods
{
    public static List FindAll(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,该项仍然会被添加到列表中。开发者对此做了修复,并感谢评论者的指正。

这是一个非常棒的解决方案,特别适用于动态创建任意数量的谓词。

0