[英]Exclude results from Linq query excluding everything when exclude list is empty
我有以下代码:
public IList<Tweet> Match(IEnumerable<Tweet> tweetStream, IList<string> match, IList<string> exclude)
{
var tweets = from f in tweetStream
from m in match
where f.Text.ToLowerInvariant().Contains(m)
select f;
var final = from f in tweets
from e in exclude
where !f.Text.ToLowerInvariant().Contains(e.ToLowerInvariant())
select f;
return final.Distinct().ToList<Tweet>();
}
我一直在构建尚未包含final
结果集的测试,并且一直很高兴地进行匹配。现在,如果IList<string>exclude
为空,则所有项目均被删除,我添加了exclude。
因此,此测试通过了:
[TestMethod]
public void Should_exclude_items_from_exclude_list()
{
IEnumerable<Tweet> twitterStream = new List<Tweet>
{
new Tweet("I have a Mazda car"),
new Tweet("I have a ford"),
new Tweet("Mazda Rules"),
new Tweet("My Ford car is great"),
new Tweet("My renault is brill"),
new Tweet("Mazda cars are great")
};
IList<string> matches = new List<string>{"mazda","car"};
IList<string> exclude = new List<string>{"ford"};
Matcher target = new Matcher();
IList<Tweet> actual = target.Match(twitterStream, matches, exclude);
Assert.AreEqual(3, actual.Count);
}
但是此测试现在失败:
[TestMethod]
public void Should_match_items_either_mazda_or_car_but_no_duplicates()
{
IEnumerable<Tweet> twitterStream = new List<Tweet>
{
new Tweet("I have a Mazda car"),
new Tweet("I have a ford"),
new Tweet("Mazda Rules"),
new Tweet("My Ford car is great"),
new Tweet("My renault is brill"),
new Tweet("Mazda cars are great")
};
IList<string> matches = new List<string>{"mazda","car"};
IList<string> exclude = new List<string>();
Matcher target = new Matcher();
IList<Tweet> actual = target.Match(twitterStream, matches, exclude);
Assert.AreEqual(4, actual.Count);
}
我知道我缺少了一些非常简单的东西,但是在盯着代码一个小时之后,它却没有出现。
好吧,我知道为什么会失败:这是这个子句:
from e in exclude
那将是一个空集合,因此没有条目甚至可以打到where子句。
这是另一种方法:
var final = from f in tweets
let lower = f.Text.ToLowerInvariant()
where !exclude.Any(e => lower.Contains(e.ToLowerInvariant())
select f;
尽管我也考虑了msarchet的方法,但是关于此方法的好处是它只对tweetStream
一次评估-因此,即使从网络中读取tweetStream
或造成其他tweetStream
,您也不必担心。 在可能的情况下(并且方便),我尝试避免多次评估LINQ流。
当然,您可以很轻松地使整个查询成为一个查询:
var tweets = from f in tweetStream
let lower = f.Text.ToLowerInvariant()
where match.Any(m => lower.Contains(m.ToLowerInvariant())
where !exclude.Any(e => lower.Contains(e.ToLowerInvariant())
select f;
老实说,我认为这样更干净:)
所以这是怎么回事:
var final = from f in tweets
from e in exclude
where !f.Text.ToLowerInvariant().Contains(e.ToLowerInvariant())
select f;
由于第二个from为空,因此,如果我是对的,则不会评估该语句的其余部分,因此您的选择永远不会发生。
尝试像这样做
var excludeTheseTweet = from f in tweets
from e in exclude
where f.Text.ToLowerInvariant().Contains(e.ToLowerInvariant())
select f;
return tweets.Except(excludeTheseTweets).Distinct().ToList<Tweet>();
这样一来,便会得到一系列推文列表(因此,如果没有要排除的内容,它将一无所获),然后将从原始列表中删除这些项目。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.