我有两个清单:
字符串列表:
reverse
和对象列表:
var keywords = _db.KeyWords.Select(k => k.Word);
我想要实现的是过滤文章属性包含关键字的文章,例如:
var articles = _db.Articles;
是否可以在没有foreach循环的一个查询中?
一个解决方案是:
var model = articles.Where(a => a.Title.Contains(keywords) || a.Description.Contains(keywords));
但我有100个关键字,使用foreach循环是一个繁重的过程。
答案 0 :(得分:4)
简而言之,您只需要使用keywords
中包含任何单词的项目。因此,在LINQ中可以通过以下方式完成:
var model = articles
.Where(a => keywords.Any(k => a.Title.Contains(k) || a.Description.Contains(k)))
.ToList();
如果标题或说明不包含keywords
中的任何字词,则不会将其添加到结果列表中。
请注意,与foreach
相比,它不会提高时间复杂度,但可能会提高可读性
一般来说,任何迭代所有关键字和文章的算法都会采用大约 Number of articles * Number of keywords * Average length of article
操作,这些操作在变量增长时会非常快速地增长。记住这一点。
答案 1 :(得分:2)
我怀疑你的foreach风格的例子是错误的。如果您的文章包含"foo bar"
以及关键字"foo"
和"bar"
,则该文章将包含两次。
您希望先浏览文章,然后再通过关键字。这是没有任何linq的:
List<Article> model = new List<Article>();
foreach (var article in articles)
{
foreach (var keyword in keywords)
{
if (article.Title.Contains(keyword) || article.Description.Contains(keyword))
{
model.Add(article);
break;
}
}
}
将其转换为linq查询非常简单:
var model = articles.Where(
a => keywords.Any(
k => a.Title.Contains(k) || a.Description.Contains(k))).ToList();
答案 2 :(得分:2)
您可以使用Any
扩展程序执行此操作。
为您的解决方案:
var model = articles
.Where(a => !keywords.Any(k => a.Title.Contains(k) || a.Description.Contains(k)))
.ToList();
以下是了解该方法的基本示例:
public class Person
{
public string Name { get; set; }
public string Pet { get; set; }
}
List<string> animals = new List<string>();
animals.Add("donkey");
animals.Add("horse");
List<Person> people = new List<Person>();
people.Add(new Person()
{
Name = "Marco",
Pet = "horse"
});
people.Add(new Person()
{
Name = "John",
Pet = "donkey"
});
people.Add(new Person()
{
Name = "Penny",
Pet = "dog"
});
//result will only include people who have pets that are in the animal list.
var res = people.Where(p => animals.Any(a => p.Pet.Contains(a)));
foreach (var item in res)
{
Console.WriteLine("{0}-{1}", item.Name, item.Pet);
}
Console.ReadLine();