我有一个集合,我想以编程方式向LINq查询添加OR条件。我知道如何添加如下的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'在一起,我该怎么做? I.E.如果我知道我将永远同时拥有两个不同的值,我就能做到这一点:
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。
答案 0 :(得分: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);
答案 1 :(得分:0)
LINQ中没有添加剂“或”。组合“Where”表达式始终被评估为“和”。
但是,您可以构建谓词,将它们添加到列表中,然后测试它们。我认为这段代码可以满足您的需求:
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}");
}
}
}