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循环是一个繁重的过程。

Linq,其中实体属性包含另一个列表

换句话说,您只需要从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();