Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/grails/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 组合多个谓词_C#_.net 2.0_Predicate - Fatal编程技术网

C# 组合多个谓词

C# 组合多个谓词,c#,.net-2.0,predicate,C#,.net 2.0,Predicate,在c#.NET2.0中有什么办法吗!要组合多个谓词 假设我有以下代码 List<string> names = new List<string>(); names.Add("Jacob"); names.Add("Emma"); names.Add("Michael"); names.Add("Isabella"); names.Add("Ethan"); names.Add("Emily"); List<string> filteredNames = na

在c#.NET2.0中有什么办法吗!要组合多个谓词

假设我有以下代码

List<string> names = new List<string>();
names.Add("Jacob");
names.Add("Emma");
names.Add("Michael");
names.Add("Isabella");
names.Add("Ethan");
names.Add("Emily");

List<string> filteredNames = names.FindAll(StartsWithE);

static bool StartsWithE(string s)
{
    if (s.StartsWith("E"))
    {
        return true;
    }
    else
    {
        return false;
    }
}
这是很酷的东西,但我知道我希望能够使用多个谓词进行过滤

所以我想说这样的话:

List<string> filteredNames = names.FindAll(StartsWithE OR StartsWithI);
List<string> filtered = names.FindAll((new StartsWithPredicate("E", "I")).StartsWith);
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));
我怎样才能做到这一点? 目前,我只是过滤两次完整的列表,然后合并结果。但不幸的是,这是相当低效的,更重要的是,我失去了原来的排序顺序,这在我的情况下是不可接受的

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

同样,它需要一个.NET2.0解决方案。不幸的是,我不能使用更新版本的框架


非常感谢。

您可以创建第三个谓词,对结果进行内部OR运算。我想你可以用lambda表达式在飞行中完成这项工作。类似这样(这不是lambda表达式,因为我不太擅长使用snytax):


您可以将谓词方法包装到类中,并让构造函数接受要测试的字符串数组:

class StartsWithPredicate
{
    private string[] _startStrings;
    public StartsWithPredicate(params string[] startStrings)
    {
        _startStrings = startStrings;
    }
    public bool StartsWith(string s)
    {
        foreach (var test in _startStrings)
        {
            if (s.StartsWith(test))
            {
                return true;
            }
        }
        return false;
    }
}
然后你可以这样打电话:

List<string> filteredNames = names.FindAll(StartsWithE OR StartsWithI);
List<string> filtered = names.FindAll((new StartsWithPredicate("E", "I")).StartsWith);
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));
List filtered=names.FindAll((新的StartsWithPredicate(“E”、“I”)).StartsWith);
这样,您就可以测试输入字符串的任何组合,而无需使用
StartsWith
方法的新变体扩展代码库。

如何:

public static Predicate<T> Or<T>(params Predicate<T>[] predicates)
{
    return delegate (T item)
    {
        foreach (Predicate<T> predicate in predicates)
        {
            if (predicate(item))
            {
                return true;
            }
        }
        return false;
    };
}

不过,我并不十分喜欢后一种方法——这感觉有点像是滥用了多播。

在.NET 2.0中,可以使用匿名委托:

List<string> filteredNames = names.FindAll(
   delegate(string s) { return StartsWithE(s) OR StartsWithI(s); }
);
List filteredNames=names.FindAll(
委托(字符串s){return StartsWithE(s)或StartsWithI(s);}
);
事实上,您也可以使用它来替换您的函数:

List<string> filteredNames = names.FindAll(
   delegate(string s) { return s.StartsWith("E") || s.StartsWith("I"); }
);
List filteredNames=names.FindAll(
委托(字符串s){返回s.StartsWith(“E”)| | s.StartsWith(“I”)}
);

我想你可以这样写:

List<string> filteredNames = names.FindAll(StartsWithE OR StartsWithI);
List<string> filtered = names.FindAll((new StartsWithPredicate("E", "I")).StartsWith);
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));
Func-predicate1=s=>s.StartsWith(“E”);
Func predicate2=s=>s.StartsWith(“I”);
Func combinedOr=s=>(谓词1(s)| |谓词2(s));
Func combinedAnd=s=>(谓词1和谓词2);

。。。等等。

我最近刚刚提出了一个类似于这个问题的解决方案,这可能也会有所帮助。我扩展了列表的FindAll方法,允许我根据需要在列表中堆叠谓词:

public static class ExtensionMethods
{
    public static List<T> FindAll<T> (this List<T> list, List<Predicate<T>> predicates)
    {
        List<T> L = new List<T> ();
        foreach (T item in list)
        {
            bool pass = true;
            foreach (Predicate<T> p in predicates)
            {
                if (!(p (item)))
                {
                    pass = false;
                    break;
                }
            }
            if (pass) L.Add (item);
        }
        return L;
    }
}
公共静态类扩展方法
{
公共静态列表FindAll(此列表,列表谓词)
{
列表L=新列表();
foreach(列表中的T项)
{
布尔传递=真;
foreach(谓词中的谓词p)
{
如果(!(p(项目)))
{
通过=错误;
打破
}
}
如果(通过)L.添加(项目);
}
返回L;
}
}
它返回一个列表,其中只有与所有给定谓词匹配的项。当然,它可以很容易地更改为或所有谓词,而不是AND。但仅凭这一点,就可以组合出各种各样的逻辑组合

用法:

{
    List<Predicate<int>> P = new List<Predicate<int>> ();
    P.Add (j => j > 100);
    P.Add (j => j % 5 == 0 || j % 7 == 0);
    P.Add (j => j < 1000);

    List<int> L = new List<int> () { 0, 1, 2, ... 999, 1000 }
    List<int> result = L.FindAll (P);

    // result will contain: 105, 110, 112, 115, 119, 120, ... 994, 995 
}
{
列表P=新列表();
P.增加(j=>j>100);
P.加(j=>j%5==0 | | j%7==0);
P.增加(j=>j<1000);
列表L=新列表(){0,1,2,…999,1000}
列表结果=L.FindAll(P);
//结果将包含:105110112115119120,…994995
}

在上述“params”数组方法中广泛使用了此模式后,我最近对多播代理的学习很感兴趣。由于委托本身就支持列表(或多播),因此可以跳过params[]模式,只向Test()函数提供一个委托。您需要对提供的谓词调用GetInvokationList。看到这个:

我当然可以,但就像在这个例子中,有大量的组合。甚至没有考虑过组合三个过滤器。。。同样不幸的是,我只能使用.NET2.0Ah,这很不幸。我相信如果你有匿名委托或lambda表达式,它会给你你想要的“即时”合成能力。非常方便。ICollectionView上的筛选器需要多个谓词。整个函数可以缩短为
return item=>predicates.All(predicate=>predicate(item))@SLC:当然-如果您使用的是LINQ。请注意,该问题需要.NET2.0。(他们可能已经能够使用lambda表达式,但我们不知道OP使用的是哪个版本的VS。)您的代码有一个bug。第一个中断仍然会导致该项被添加到列表中……即使谓词返回false。@MylesJ-您是对的,它现在已修复。谢谢你通知我!如果动态创建任意数量的谓词,这是唯一有效的解决方案。回答得好!您不需要在组合函数中调用谓词函数吗?