C# 使用LINQ缩小结果集
假设我有一个名为C# 使用LINQ缩小结果集,c#,linq,collections,join,lambda,C#,Linq,Collections,Join,Lambda,假设我有一个名为GetCatsByColor的方法,该方法将颜色作为字符串,方法GetCatsByName将名称作为字符串,方法GetCatsByBirthDate将两个DateTime作为时间范围 现在假设我有一个CatFilter类,它包含一个List名称、List颜色和两个DateTimes,表示时间跨度的“from”日期和“to”日期。我要做的是创建一个GetFilteredCats方法,该方法接受这些Filter对象之一,并返回满足给定Filter规范的CAT集合 我很难想出一种获得所
GetCatsByColor
的方法,该方法将颜色作为字符串,方法GetCatsByName
将名称作为字符串,方法GetCatsByBirthDate
将两个DateTime
作为时间范围
现在假设我有一个CatFilter
类,它包含一个List
名称、List
颜色和两个DateTime
s,表示时间跨度的“from”日期和“to”日期。我要做的是创建一个GetFilteredCats
方法,该方法接受这些Filter
对象之一,并返回满足给定Filter
规范的CAT集合
我很难想出一种获得所需结果的有效方法,最好使用LINQ/lambda表达式
进行这种连接的最佳方式是什么?我应该看什么扩展方法?在
foreach
循环中修改集合通常是不可取/不可能的,所以我的策略应该是什么?正确的方法是使方法GetFilteredCats
,接受您的筛选器并通过LINQ组合返回正确的CAT:
IEnumerable<Cat> cats = //.. get all cats here
if (filter.FilterByColor)
cats = cats.Where(c=>c.Color = filter.Color);
if (filter.FilterByName)
cats = cats.Where(c=>c.Name = filter.Name);
if (filter.FilterByDate)
cats = cats.Where(c=>c.Date > filter.FromDate && c.Date < filter.ToDate)
return cats.ToList(); // finally filter data and return them.
IEnumerable猫=/。。把所有的猫都带过来
if(filter.FilterByColor)
cats=cats.Where(c=>c.Color=filter.Color);
if(filter.FilterByName)
cats=cats.Where(c=>c.Name=filter.Name);
if(过滤器。过滤器水化物)
cats=cats.Where(c=>c.Date>filter.FromDate&&c.Date
在表演的情况下。我认为用不同的方法在逻辑上不可能做到这一点。但当你开始接触数以百万计的猫时,这将成为一个问题。此时,应该使用数据库。为了您的方便,它们具有智能的索引和聚类功能。正确的方法是使用方法
GetFilteredCats
,接受您的过滤器并通过LINQ组合返回正确的CAT:
IEnumerable<Cat> cats = //.. get all cats here
if (filter.FilterByColor)
cats = cats.Where(c=>c.Color = filter.Color);
if (filter.FilterByName)
cats = cats.Where(c=>c.Name = filter.Name);
if (filter.FilterByDate)
cats = cats.Where(c=>c.Date > filter.FromDate && c.Date < filter.ToDate)
return cats.ToList(); // finally filter data and return them.
IEnumerable猫=/。。把所有的猫都带过来
if(filter.FilterByColor)
cats=cats.Where(c=>c.Color=filter.Color);
if(filter.FilterByName)
cats=cats.Where(c=>c.Name=filter.Name);
if(过滤器。过滤器水化物)
cats=cats.Where(c=>c.Date>filter.FromDate&&c.Date
在表演的情况下。我认为用不同的方法在逻辑上不可能做到这一点。但当你开始接触数以百万计的猫时,这将成为一个问题。此时,应该使用数据库。为了您的方便,它们具有智能的索引和集群功能。类似的功能应该可以工作,请注意,它没有经过测试
List<string> names = new List<string>();
List<Color> colors = new List<Color>();
List<DateTime> dobs = new List<DateTime>();
List<cat> cats = new List<cat>();
var filtered = from c in cats
join n in names on c.name equals n
join cl in colors on c.color equals cl
join db in dobs on c.dob equals db
select c;
列表名称=新列表();
列表颜色=新列表();
List dobs=新列表();
列表猫=新列表();
过滤的var=猫的c
在c上的名称中加入n。名称等于n
在c上的颜色中加入cl。颜色等于cl
在c上的dobs中加入db。dob等于db
选择c;
您还可以有一些带有两个日期的列表,在这种情况下,您需要输入where条件,其中c.dob=date2,或者类似的内容。
希望这能有所帮助。类似的功能应该可以工作,请注意,它没有经过测试
List<string> names = new List<string>();
List<Color> colors = new List<Color>();
List<DateTime> dobs = new List<DateTime>();
List<cat> cats = new List<cat>();
var filtered = from c in cats
join n in names on c.name equals n
join cl in colors on c.color equals cl
join db in dobs on c.dob equals db
select c;
列表名称=新列表();
列表颜色=新列表();
List dobs=新列表();
列表猫=新列表();
过滤的var=猫的c
在c上的名称中加入n。名称等于n
在c上的颜色中加入cl。颜色等于cl
在c上的dobs中加入db。dob等于db
选择c;
您还可以有一些带有两个日期的列表,在这种情况下,您需要输入where条件,其中c.dob=date2,或者类似的内容。
希望这有帮助。您可以使用表达式树。当CatFilter对象被传递到GetFilteredCats方法时,根据在该对象上设置的属性,您将生成表达式(如下面的伪代码所示),将这些表达式连接起来并用于构建完整的LINQ查询 比如:
Expression catFilter =
from cat in Cats
where <Expression> and <Expression> and ...
select cat
表达式catFilter=
从《猫中的猫》
在哪里和。。。
选择猫
然后简单地编译(Expression.compile)并执行 可以使用表达式树。当CatFilter对象被传递到GetFilteredCats方法时,根据在该对象上设置的属性,您将生成表达式(如下面的伪代码所示),将这些表达式连接起来并用于构建完整的LINQ查询 比如:
Expression catFilter =
from cat in Cats
where <Expression> and <Expression> and ...
select cat
表达式catFilter=
从《猫中的猫》
在哪里和。。。
选择猫
然后简单地编译(Expression.compile)并执行 我通常做的是在where子句中进行检查,检查在执行实际筛选之前是否需要筛选。当运行时需要计算过滤器时,如果不需要,则会完全跳过该过滤器
public class CatFilter
{
public List<string> Names = new List<string>();
public List<string> Colors = new List<string>();
public DateTime? BirthDateStartRange = null;
public DateTime? BirthDateEndRange = null;
}
public List<Cat> GetFilteredCats(CatFilter filter)
{
List<Cat> result = new List<Cat>();
var query = cats
.Where(a => !filter.Names.Any() || filter.Names.Contains(a.Name))
.Where(a => !filter.Colors.Any() || filter.Colors.Contains(a.Color))
.Where(a => filter.BirthDateStartRange == null || a.DateOfBirth >= filter.BirthDateStartRange)
.Where(a => filter.BirthDateEndRange == null || a.DateOfBirth <= filter.BirthDateEndRange);
result.AddRange(query);
return result;
}
公共类CatFilter
{
公共列表名称=新列表();
公共列表颜色=新列表();
公共日期时间?BirthDateStartRange=null;
public DateTime?BirthDateEndRange=null;
}
公共列表GetFilteredCats(CatFilter过滤器)
{
列表结果=新列表();
var query=cats
.Where(a=>!filter.Names.Any()| | filter.Names.Contains(a.Name))
.Where(a=>!filter.Colors.Any()| | filter.Colors.Contains(a.Color))
.Where(a=>filter.BirthDateStartRange==null | | a.DateOfBirth>=filter.BirthDateStartRange)
.Where(a=>filter.BirthDateEndRange==null | | a.DateOfBirth我通常做的是在Where子句中进行检查,检查在执行实际筛选之前是否需要筛选。当运行时需要评估筛选时,如果不需要,则完全跳过它
public class CatFilter
{
public List<string> Names = new List<string>();
public List<string> Colors = new List<string>();
public DateTime? BirthDateStartRange = null;
public DateTime? BirthDateEndRange = null;
}
public List<Cat> GetFilteredCats(CatFilter filter)
{
List<Cat> result = new List<Cat>();
var query = cats
.Where(a => !filter.Names.Any() || filter.Names.Contains(a.Name))
.Where(a => !filter.Colors.Any() || filter.Colors.Contains(a.Color))
.Where(a => filter.BirthDateStartRange == null || a.DateOfBirth >= filter.BirthDateStartRange)
.Where(a => filter.BirthDateEndRange == null || a.DateOfBirth <= filter.BirthDateEndRange);
result.AddRange(query);
return result;
}
公共类CatFilter
{
P