假设我有一个名为GetCatsByColor
的方法,它将颜色作为字符串,方法GetCatsByName
将名称作为字符串,GetCatsByBirthDate
采用两个DateTime
这是一段时间。
现在说我有一个CatFilter
类,其中包含List
个名称,List
个颜色和两个DateTime
s,代表“来自”日期和“到”时间的日期。我要做的是创建一个GetFilteredCats
方法,该方法接受其中一个Filter
个对象,并返回符合给定Filter
规范的Cats集合。
我很难想出一种获得理想结果的有效方法,理想情况下使用LINQ / lambda表达式。
进行此类加入的最佳方式是什么?我应该考虑哪些扩展方法?通常不建议/可能在foreach
循环中修改集合,那么我的策略应该是什么?
答案 0 :(得分:1)
我通常做的是检查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;
}
然后像这样称呼它
cats.Add(new Cat("Felix", "Black", DateTime.Today.AddDays(-1)));
cats.Add(new Cat("Garfield", "Orange", DateTime.Today.AddDays(-10)));
CatFilter filter = new CatFilter();
filter.Names.Add("Garfield");
List<Cat> result = GetFilteredCats(filter);
答案 1 :(得分:0)
正确的方法是制作方法GetFilteredCats
,接受你的过滤器并通过LINQ组合返回正确的猫:
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.
如果有表现。我不认为这可以用不同的方法来完成。但是当你开始击中数百万只猫时,这将成为问题。此时,应该使用数据库。为方便起见,它们具有聪明的索引和聚类。
答案 2 :(得分:0)
这样的东西应该有用,请注意它没有经过测试
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;
你也可以有一些带有两个日期的列表,在这种情况下你需要设置一个where条件,其中c.dob&lt; = date1&amp;&amp; c.dob&gt; = date2,或类似的东西。 希望这会有所帮助。
答案 3 :(得分:0)
您可以使用表达式树。当CatFilter对象传递给GetFilteredCats方法时,根据在此对象上设置的属性,您生成表达式(即在下面的伪代码中看到),您将连接并用于构建完整的LINQ查询。
类似的东西:
Expression catFilter =
from cat in Cats
where <Expression> and <Expression> and ...
select cat
然后简单地编译(Expression.Compile)并执行。