【问题标题】:How to find all items in List<T> that matches multiple criteria如何查找 List<T> 中匹配多个条件的所有项目
【发布时间】:2013-12-19 14:32:30
【问题描述】:

我有一个产品清单。我想根据可以包含多个关键字的多个字符串对象过滤列表。

我尝试了几个选项,如下所示:

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

预期的结果集是选项 3 的结果集:产品 ID 1、3、4 和 5

有没有更好的方法来做我想做的事?

【问题讨论】:

  • 您目前的方法有问题吗?
  • 您可以对代码进行一些改进,只进行一次拆分(查询字符串、流派、艺术家)
  • @lazyberezovsky :不,我没有任何问题,我只是认为代码可以改进。
  • Thnx @Alberto,我会这样做的。

标签: c# linq list filter


【解决方案1】:

由于您在那里的 linq 语句最终将运行每个项目并在每个项目上调用 ContainsAny,因此您最终还将执行每个项目的拆分函数。

但是,您可以使用 let 关键字让 split 函数被调用一次。

这里是 let 关键字的链接。

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

此外,由于您在代码的底部使用了这些拆分函数,我建议您创建一个数组类型的变量并在代码的顶部执行一次拆分,以便您的 linq 语句和底部不需要多次调用split。

如果您选择这种方法,您将不需要在 linq 中使用 ley 关键字。

【讨论】:

  • 谢谢@devhedgehog。我刚刚更新了我的代码,现在我正在使用我的代码的选项 3,并进行了一些改进。我采用了创建变量的方式来执行拆分功能。
猜你喜欢
  • 2012-03-05
  • 1970-01-01
  • 1970-01-01
  • 2011-11-30
  • 1970-01-01
  • 2021-12-03
  • 2015-04-28
  • 2018-10-17
  • 1970-01-01
相关资源
最近更新 更多