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

时间:2015-12-04 09:31:34

标签: c# linq

我有两个清单:

字符串列表:

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

3 个答案:

答案 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();