简体   繁体   English

如何查找列表中的所有项目 <T> 符合多个条件

[英]How to find all items in List<T> that matches multiple criteria

I have a list with products. 我有一个产品清单。 I would like to filter the list based on multiple string objects that can contain multiple keywords. 我想基于可以包含多个关键字的多个字符串对象过滤列表。

I tried several options as you can see below: 我尝试了几种选择,如下所示:

List<Product> products = new List<Product>();
        products.Add(new Product() { Id = 1, Title = "Dit is product 1", Genre = "genre 1, genre 2, genre 4", Artist = "artist 1, artist 3"});
        products.Add(new Product() { Id = 2, Title = "Johan Bach", Genre = "genre 3, genre 4, genre 6", Artist = "artist 3, artist 4" });
        products.Add(new Product() { Id = 3, Title = "Straus is klaus", Genre = "genre 8, genre 7", Artist = "artist 9" });
        products.Add(new Product() { Id = 4, Title = "Sebastiaan buch", Genre = "genre 9, genre 2, genre 3", Artist = "artist 5, artist 6" });
        products.Add(new Product() { Id = 5, Title = "Beethoven rocks", Genre = "genre 5, genre 8, genre 11", Artist = "artist 1, artist 8" });

        string querystring = "dit buch beethove";
        string genre = "";
        string artist = "artist 9";

        var keys = querystring.Split(' ');

        Console.WriteLine("");
        Console.WriteLine("optie 1:");
        List<Product> result = products.FindAll(s => 
            s.Title.ContainsAny(keys) ||
            s.Genre.ContainsAny(genre.Split(',')) ||
            s.Artist.ContainsAny(artist.Split(','))
            );

        foreach (var product in result)
        {
            Console.WriteLine(product.Title);
        }

        Console.WriteLine("");
        Console.WriteLine("optie 2:");
        List<Product> option2 = products;
        if (querystring.Length > 0 && querystring.Split(' ').Any())
            option2 = option2.Where(s => s.Title.ContainsAny(querystring.Split(' '))).ToList();
        if (genre.Length > 0 && genre.Split(',').Any())
            option2 = option2.Where(s => s.Genre.ContainsAny(genre.Split(','))).ToList();
        if (artist.Length > 0 && artist.Split(',').Any())
            option2 = option2.Where(s => s.Artist.ContainsAny(artist.Split(','))).ToList();

        foreach (var product in option2)
        {
            Console.WriteLine(product.Title);
        }

        Console.WriteLine("");
        Console.WriteLine("optie 3:");
        List<Product> results = new List<Product>();
        if (querystring.Length > 0 && querystring.Split(' ').Any())
        {
            results = results = products.FindAll(s => s.Title.ContainsAny(keys));
        }
        if (genre.Length > 0 && genre.Split(',').Any())
        {
            results = results.Union(products.FindAll(s => s.Genre.ContainsAny(genre.Split(',')))).ToList();
        }
        if (artist.Length > 0 && artist.Split(',').Any())
        {
            results = results.Union(products.FindAll(s => s.Artist.ContainsAny(artist.Split(',')))).ToList();
        }

        foreach (var product in results)
        {
            Console.WriteLine(product.Title);
        }


        Console.ReadLine();

The result set that would be expected is the resultset of option 3: product ids 1,3,4,and 5 预期的结果集是选项3的结果集:产品ID 1、3、4和5

Is there a better way of doing what I would like to do ? 有没有更好的方式做我想做的事?

Since the linq statement you have there will eventually run though each item and call ContainsAny on each item you will also end up executing the split function per item. 由于那里的linq语句最终将遍历每个项目,并在每个项目上调用ContainsAny,因此您还将最终执行每个项目的split函数。

You could however use the let keyword to let the split function been called once. 但是,您可以使用let关键字让split函数一次被调用。

Here is a link to let keyword. 这是let关键字的链接。

http://msdn.microsoft.com/en-us/library/bb383976.aspx http://msdn.microsoft.com/en-us/library/bb383976.aspx

Futhermore since you are using those split functions in the bottom part of your code I would suggest you to create a variable of array type and do the split once in the top part of your code so that your linq statement and the bottom part do not need to call split various times. 另外,由于您在代码的底部使用了这些拆分函数,因此建议您创建一个数组类型的变量,并在代码的顶部进行一次拆分,这样您的linq语句和底部就不需要了多次调用拆分。

If you pick this approach you will not need to use the ley keyword in linq. 如果选择这种方法,则无需在linq中使用ley关键字。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM