检查字符串是不是包含子字符串列表并保存匹配的子字符串
Posted
技术标签:
【中文标题】检查字符串是不是包含子字符串列表并保存匹配的子字符串【英文标题】: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
的答案不会。
【参考方案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<string>
并与两个集合相交:
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();
【讨论】:
以上是关于检查字符串是不是包含子字符串列表并保存匹配的子字符串的主要内容,如果未能解决你的问题,请参考以下文章
如何检查字符串是不是包含 JavaScript 中的子字符串?