【问题标题】:Check if a string contains a list of substrings and save the matching ones检查字符串是否包含子字符串列表并保存匹配的子字符串
【发布时间】:2015-07-27 11:20:18
【问题描述】:

这是我的情况:我有一个代表文本的字符串

string myText = "Text to analyze for words, bar, foo";   

以及要在其中搜索的单词列表

List<string> words = new List<string> {"foo", "bar", "xyz"};

我想知道获取文本中包含的单词列表的最有效方法(如果存在),类似于:

List<string> matches = myText.findWords(words)

【问题讨论】:

  • 在 CPU 时间或内存方面效率高吗?
  • myText 的大小是多少以及您将执行多少搜索操作/
  • 您需要定义“单词”的含义。 “foo”是否应该在“This is foobar”这样的字符串中匹配? Contains 的答案会匹配,而Split 的答案不会。

标签: c# string contains


【解决方案1】:

除了必须使用Contains 方法外,此查询没有特殊分析。所以你可以试试这个:

string myText = "Text to analyze for words, bar, foo";

List<string> words = new List<string> { "foo", "bar", "xyz" };

var result = words.Where(i => myText.Contains(i)).ToList();
//result: bar, foo

【讨论】:

  • 这可能是最好的选择,考虑到编码时间的效率(不应忽略)
  • @DrewKennedy 只要问题不复杂,为什么不选择最简单紧凑的解决方案
  • @HosseinNarimaniRad 我同意这没关系。我认为评论指的是这种方法需要多次传递字符串,这不是必需的。此外,如果单词相对较长,还有 Boyer-Moore-Horspool 算法可以显着加快算法速度。
  • @Bas 谢谢。我要检查 Boyer-Moore-Horspool 算法
  • 应该注意,这将匹配字符串中的“foo”,例如“This is foobar”,这可能是也可能不是想要的结果。
【解决方案2】:

您可以使用 HashSet&lt;string&gt; 并与两个集合相交:

string myText = "Text to analyze for words, bar, foo"; 
string[] splitWords = myText.Split(' ', ',');

HashSet<string> hashWords = new HashSet<string>(splitWords,
                                                StringComparer.OrdinalIgnoreCase);
HashSet<string> words = new HashSet<string>(new[] { "foo", "bar" },
                                            StringComparer.OrdinalIgnoreCase);

hashWords.IntersectWith(words);

【讨论】:

  • 虽然它处理给定的示例,但它不适用于像“这里是 foo!bar 在哪里?我是 xyz。”这样的字符串。基本上,您需要拆分任何可以分隔单词的内容。 OP也没有提到“foo”是否应该在“This is foobar”这样的字符串中匹配。
  • @juharr 这是 OP 可以使用 HashSet 做什么的示例。他可以在任何他想要的分隔符上进行拆分。他还可以在将字符串插入集合之前修剪字符串,我没有这样做。
  • 我完全同意,如果 OP 想要查看单词而不仅仅是任何子字符串,这是要走的路。我只是觉得应该指出,拆分过程可能更复杂。
【解决方案3】:

正则表达式解决方案

var words = new string[]{"Lucy", "play", "soccer"};
var text = "Lucy loves going to the field and play soccer with her friend";
var match = new Regex(String.Join("|",words)).Match(text);
var result = new List<string>();

while (match.Success) {
    result.Add(match.Value);
    match = match.NextMatch();
}

//Result ["Lucy", "play", "soccer"]

【讨论】:

  • 你应该使用 Regex.Escape
【解决方案4】:

根据您希望能够使用myText.findWords(words) 的想法,您可以为 String 类创建一个扩展方法来做您想做的事情。

public static class StringExtentions
{
    public static List<string> findWords(this string str, List<string> words)
    {
        return words.Where(str.Contains).ToList();
    }
}

用法:

string myText = "Text to analyze for words, bar, foo";
List<string> words = new List<string> { "foo", "bar", "xyz" };
List<string> matches = myText.findWords(words);
Console.WriteLine(String.Join(", ", matches.ToArray()));
Console.ReadLine();

结果:

富,酒吧

【讨论】:

    【解决方案5】:

    下面是一个简单的解决空格和标点符号的方法:

    static void Main(string[] args)
    {
        string sentence = "Text to analyze for words, bar, foo";            
        var words = Regex.Split(sentence, @"\W+");
        var searchWords = new List<string> { "foo", "bar", "xyz" };
        var foundWords = words.Intersect(searchWords);
    
        foreach (var item in foundWords)
        {
            Console.WriteLine(item);
        }
    
        Console.ReadLine();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-11-09
      • 2013-05-18
      • 2021-12-20
      • 2014-11-22
      • 2013-02-05
      • 2021-12-14
      • 1970-01-01
      相关资源
      最近更新 更多