【问题标题】:Get all objects in a list where a string parameter contains all strings in second list获取列表中的所有对象,其中字符串参数包含第二个列表中的所有字符串
【发布时间】:2015-03-21 19:14:25
【问题描述】:

我有一个自定义对象列表“CustomFile”——这些对象包含各种数据以及一个“title”字符串参数。该列表本身称为“AllFiles”。

我在列表框中向用户显示“AllFiles”列表(用户只能看到每个“CustomFile”对象的“title”字符串)。

我还有一个搜索框,用户可以在其中输入搜索字符串。然后应该向他显示根据“标题”参数过滤的文件列表。

“AllFiles”列表示例如下所示:

  • [1] MS Excel 文档
  • [2] MS Excel 教程
  • [3] MS Access 文档
  • [4] MS Access 教程
  • [5] 谷歌浏览器文档
  • [6] 适用于 Chrome 的 Google 产品视频

我使用了一个 LINQ 查询,它选择所有“自定义文件”,其中“标题”包含搜索查询。

因此,如果用户搜索“文档”,他会看到项目 1、3 和 5。但如果他搜索“ms 文档”,他将不会得到任何结果,因为在“AllFiles”中没有与“ms 文档”完全匹配”。

现在我想让搜索更加灵活一些。在搜索“ms 文档”时,用户应该看到项目 1 和 3。同样,如果用户搜索“google chrome”,他应该看到项目 5 和 6,即使 6 不包含确切的文本“google chrome”。

基本上,我需要在“所有文件”列表中搜索“标题”包含搜索查询中所有单词的对象,无论单词的顺序如何。

所以我将搜索查询拆分为字符串列表 (listSearchWords)。如果用户搜索“google chrome”,我有一个包含条目 [1]“google”和 [2]“chrome”的列表。但是现在我被困在下一步该怎么做。

文件和搜索查询中的单词数量当然是动态的,所以我不能只做“包含第 1 项或包含第 2 项”。我需要以某种方式过滤“标题”包含来自 listSearchWords 的所有字符串的对象的“AllWords”列表。

感谢您的帮助。

编辑

通过接受的答案,我把它归结为两行:

List<string> searchTerms = searchQuery.Text.Split(' ').ToList(); 

searchQuery 是用户输入的搜索词串。

    var filteredObjects = AllObjects.Where
    (a => searchTerms.All(b => a.[string parameter on object].IndexOf
    (b, StringComparison.OrdinalIgnoreCase) >= 0)).ToList(); 
    //AllObjects is a list of the custom objects. 
    //string parameter on object] is the string variable on the custom object that I'm filtering on.

【问题讨论】:

  • 似乎 All 方法只是返回一个关于序列的所有元素是否满足特定条件的布尔值。我已经阅读并重新阅读了您链接的文章,但我不完全了解如何将其应用于我的问题。
  • 您是否在控制台应用程序中尝试过示例代码? All 方法位于 Where 方法中。外部 Where 方法将选择搜索项中满足特定条件的每个项。条件是搜索项必须包含您已标记化的所有搜索词。如果我正确理解您的问题,我真的认为这是一个合适的解决方案。
  • 是的,不过我在理解方面遇到了一些问题。当有很多嵌套命令时,Linq 语法会变得有点复杂。无论如何,由于下面的代码,我终于得到了它。非常感谢。

标签: c# linq


【解决方案1】:

您可以使用 LINQ 使用标记化的搜索词列表对查询进行表述。像这样的:

searchItems.Where(a => searchTerms.All(a.Contains))

这有效地遍历所有搜索项并返回搜索项包含每个搜索词的项。

上面是区分大小写的,如果你想让它不区分大小写,你必须尝试这样的事情:

searchItems.Where(a => searchTerms.All(b => a.IndexOf(b, StringComparison.OrdinalIgnoreCase) >= 0));

编辑:

这是一个完整的工作示例:

namespace ConsoleApplication7
{
using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        var searchItems = new List<string> { "MS Excel documentation", "MS Excel tutorial", "MS Access documentation", "MS Access tutorial", "Google Chrome documentation", "Google Product video for Chrome" };
        var searchTerms = new List<string> { "google", "chrome" };

        var searchResults = searchItems.Where(a => searchTerms.All(b => a.IndexOf(b, StringComparison.OrdinalIgnoreCase) >= 0)).ToList();

        foreach (var searchResult in searchResults)
        {
            Console.WriteLine(searchResult);
        }

        Console.ReadLine();
    }
}
}

【讨论】:

  • 这给了我一条错误消息说'System.Collections.Generic.List' 不包含'All' 的定义和最佳扩展方法重载'System.Linq.Enumerable.All (System.Collections.Generic.IEnumerable, System.Func)' 有一些无效参数。抱歉,如果我在这里遗漏了一些明显的东西。
  • 这可能与缺少命名空间导入有关。我将发布一个完整的示例,请稍等。
【解决方案2】:

您可以根据需要修改示例代码。

 List<string> a = new List<string>();
        a.Add("[1] MS Excel documentation");
        a.Add("[2] MS Excel tutorial");
        a.Add("[3] MS Access documentation");
        a.Add("[4] MS Access tutorial");
        a.Add("[5] Google Chrome documentation");
        a.Add("[6] Google Product video for Chrome");
        var result = from item in a
                     let x = "MS"
                     let y = "documentation"
                     where item.Contains(x) && item.Contains(y)
                     select item;
        foreach (var item in result)
        {
            Console.WriteLine(item);
        }

【讨论】:

  • "ms documentation" 是运行时的用户输入,因此在编译时是未知的。这意味着您的解决方案不适合它。
  • @zerkms,你可以修改它。说let x=args[0]等。试试看。
  • 天哪,输入是 A STRING"this is a list of search terms"。请更加小心,并花一些额外的时间重新阅读问题和我的 cmets。谢谢。
  • 我认为这对我没有多大帮助,因为搜索词是动态的,这意味着可以有任意数量的搜索词,而不仅仅是像您的示例中的 2 个。可能可以修改为动态的,但不幸的是我不知道如何。不过谢谢!
  • @MortenK,那你可以用这个思路重写一个where子句的扩展方法,不难。有时间我可以试试。
【解决方案3】:

如果你写一个扩展方法。可以达到目的。

 class Program
{
    static void Main()
    {
        List<string> a = new List<string>();
        a.Add("[1] MS Excel documentation");
        a.Add("[2] MS Excel tutorial");
        a.Add("[3] MS Access documentation");
        a.Add("[4] MS Access tutorial");
        a.Add("[5] Google Chrome documentation");
        a.Add("[6] Google Product video for Chrome");
        string search = "MS documentation";
        var result = a.WhereExtension(search);
        foreach (var item in result)
        {
            Console.WriteLine(item);
        }
        Console.ReadLine();
    }
}
public static class MyExtensions
{
    public static List<string> WhereExtension(this List<string> source, string items)
    {
        var search = items.Split(' ');
        List<string> list = new List<string>();
        foreach (string item in source)
        {
            bool add = true;
            for (int i = 0; i < search.Count(); i++)
            {
                if (!item.Contains(search[i]))
                    add = false;
            }
            if (add == true)
                list.Add(item);
        }
        return list;
    }
}

【讨论】:

  • 谢谢,不过我使用已接受的答案建议将其简化为两行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-31
  • 1970-01-01
  • 2012-10-11
  • 2021-06-07
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多