Linq,其中实体属性包含另一个列表
本文关键字:包含 另一个 列表 属性 实体 Linq | 更新日期: 2023-09-27 18:25:41
我有两个列表:
字符串列表:
var keywords = _db.KeyWords.Select(k => k.Word);
和对象列表:
var articles = _db.Articles;
我想要实现的是过滤文章属性包含关键字的文章,例如:
var model = articles.Where(a => a.Title.Contains(keywords) || a.Description.Contains(keywords));
在一个没有foreach循环的查询中是否可能?
一种解决方案是:
List<Article> model = new List<Article>();
foreach (var keyword in keywords)
{
model.AddRange(articles.Where(a => a.Title.Contains(keyword) || a.Description.Contains(keyword)));
}
但我有100个关键词,使用foreach循环是一个繁重的过程。
换句话说,您只需要从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
运算,当变量增长时,运算增长得非常快。记住这一点。
您可以使用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();
我怀疑您的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();