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