Nat*_*han 1 c# linq-to-objects
我有以下代码:
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>();
}
Run Code Online (Sandbox Code Playgroud)
我一直在构建测试,其中没有包含final结果集并且已经愉快地匹配现在我已添加了排除如果IList<string>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);
}
Run Code Online (Sandbox Code Playgroud)
但是这个测试现在失败了:
[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);
}
Run Code Online (Sandbox Code Playgroud)
我知道我错过了一些非常简单的东西,但在盯着代码一小时之后它就没有来找我.
好吧,我知道它为什么失败了:这是这个条款:
from e in exclude
Run Code Online (Sandbox Code Playgroud)
这将是一个空集合,所以甚至没有条目甚至命中where子句.
这是另一种方法:
var final = from f in tweets
let lower = f.Text.ToLowerInvariant()
where !exclude.Any(e => lower.Contains(e.ToLowerInvariant())
select f;
Run Code Online (Sandbox Code Playgroud)
虽然我也考虑过msarchet的方法,但关于这个方法的好处是它最终只会评估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;
Run Code Online (Sandbox Code Playgroud)
我认为即使更清洁,说实话:)