【问题标题】:Dynamically add Or conditions动态添加或条件
【发布时间】:2018-01-26 17:27:22
【问题描述】:

我有一个集合,我想以编程方式将 OR 条件添加到 linq 查询。我知道如何添加 AND 条件,如下所示:

var mySet = SomeFactory.GetData();
foreach(var nameFilter in nameFilters)
{
  mySet = mySet.Where(item => item.Name == nameFilter);
}
foreach(var ageFilter in ageFilters)
{
  mySet = mySet.Where(item => item.Age == ageFilter)
}

但是,如果我希望这些是 OR 条件而不是“AND”在一起,我该怎么做? IE。如果我知道我将永远拥有这两者,而不是不同值的数组,我可以这样做:

mySet.Where(item => item.Name == nameFilter[0] || item.Name == nameFilter[1] ...  || item.Age == ageFilter[0] || item.Age == ageFilter[1] || ...);

TL;DR:我希望能够将未知数量的布尔检查链接到使用 OR 语句评估的单个表达式中。例如,如果我有一个名为 Mary 或 Jim 的人的交叉引用,他们是 32 岁或 51 岁。

【问题讨论】:

  • 什么是nameFilter?单个值、逗号分隔值等?
  • 它是一个字符串...抱歉这个例子太可怕了。让我调整一下问题

标签: c# linq .net-4.6


【解决方案1】:

PredicateBuilder 将帮助您灵活地应用 where 子句。你可以找到扩展方法here

var filterOfNames = new List<string> {"Sample", "Sample2"};
var filterOfAges = new List<int> { 21, 33, 45 };
var mySet = SomeFactory.GetData();
var predicate = PredicateBuilder.True<TypeOfmySet>();
foreach (var filterOfName in filterOfNames)
{
    //If it is the first predicate, you should apply "And"
    if (predicate.Body.NodeType == ExpressionType.Constant)
    {
        predicate = predicate.And(x => x.Name == filterOfName);
        continue;
    }
    predicate = predicate.Or(x => x.Name == filterOfName);
}
foreach (var filterOfAge in filterOfAges)
{
    //If it is the first predicate, you should apply "And"
    if (predicate.Body.NodeType == ExpressionType.Constant)
    {
        predicate = predicate.And(x => x.Age == filterOfAge);
        continue;
    }
    predicate = predicate.Or(x => x.Age == filterOfAge);
}
//I don't know the myset has which type in IQueryable or already retrieved in memory collection. If it is IQueryable, don't compile the predicate otherwise compile it.
//var compiledPredicate = predicate.Compile();
mySet = mySet.Where(predicate);

【讨论】:

  • 谢谢,我看到这适用于我的内存对象,但我目前正尝试将它与 LinqToSalesforce 结合使用,但无法评估。回到绘图板。如果这个库实现了 contains 方法,我的解决方案将非常简单。感谢您的帮助。
  • 查看我的解决方案,使用包含。
  • 最后一行,当你把谓词放在“Where”里面时,你可能需要编译构建的表达式:mySet.Where(predicate.Compile())
【解决方案2】:

LINQ 中没有加法“或”。组合“Where”表达式总是被评估为“and”。

但是,您可以构建谓词,将它们添加到列表中,然后对其进行测试。我认为这段代码可以满足您的要求:

using System;
using System.Collections.Generic;

class Item
{
    internal string Name { get; set; }
    internal short Age { get; set; }
    internal string City { get; set; }
}
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)
        {
            foreach (Predicate<T> p in predicates)
            {
                if (p(item)) L.Add(item);
            }
        }
        return L;
    }
}
class Program
{
    static void Main(string[] args)
    {
        List<Item> items = new List<Item>();
        items.Add(new Item { Name = "Bob", Age = 31, City = "Denver" });
        items.Add(new Item { Name = "Mary", Age = 44, City = "LA" });
        items.Add(new Item { Name = "Sue", Age = 21, City = "Austin" });
        items.Add(new Item { Name = "Joe", Age = 55, City = "Redmond" });
        items.Add(new Item { Name = "Tom", Age = 81, City = "Portland" });

        string nameFilter = "Bob,Mary";
        //string ageFilter = "55,21";
        string ageFilter = null;
        string cityFilter = "Portland";

        List<Predicate<Item>> p = new List<Predicate<Item>>();

        if (nameFilter != null)
        {
            p.Add(i => nameFilter.Contains(i.Name));
        }

        if (cityFilter != null)
        {
            p.Add(i => cityFilter.Contains(i.City));
        }

        if (ageFilter != null)
        {
            p.Add(i => ageFilter.Contains(i.Age.ToString()));
        }

        var results = items.FindAll(p);

        foreach (var result in results)
        {
            Console.WriteLine($"{result.Name} {result.Age} {result.City}");
        }
    }
}

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-08
  • 2013-12-08
  • 2014-09-08
  • 2014-11-07
  • 2012-02-28
  • 2015-10-26
相关资源
最近更新 更多