我需要检查字符串是否包含任何脏话。
根据另一个问题的建议,我制作了一个包含单词的HashSet:
HashSet<string> swearWords = new HashSet<string>() { "word_one", "word_two", "etc" };
现在我需要查看swearWords
中包含的任何值是否在我的字符串中。
我已经看到它反过来了,例如:
swearWords.Contains(myString)
但这会返回错误。
检查HashSet中的任何单词是否在myString
中的最快方法是什么?
注意:我想我可以使用foreach循环依次检查每个单词,如果找到匹配则中断,我只是想知道是否有更快的方法。
答案 0 :(得分:10)
如果您将发誓放在IEnumerable&lt;&gt;中实施容器:
var containsSwears = swarWords.Any(w => myString.Contains(w));
注意:HashSet&lt;&gt;实现IEnumerable&lt;&gt;
答案 1 :(得分:7)
你可以试试一个正则表达式,但我不确定它是否更快。
Regex rx = new Regex("(" + string.Join("|", swearWords) + ")");
rx.IsMatch(myString)
答案 2 :(得分:7)
如果您有大量的咒骂词,您可以使用Aho-Corasick算法:http://tomasp.net/blog/ahocorasick.aspx
答案 3 :(得分:4)
此类方案的主要问题是定义您要检查的字符串上下文中的单词。
input.Contains
的天真实现根本就没有单词的概念;他们会&#34;检测&#34;即使这不是意图,也要发誓。假设您的禁用词列表仅使用拉丁字母,实际的选择是假设单词是仅由拉丁字符组成的序列。因此合理的起始解决方案将是
var words = Regex.Split(@"[^\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Pc}\p{Lm}]", myString);
上面的正则表达式是修改为不包含数字的标准类\W
;有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/20bw873z.aspx。对于其他方法,请参阅this question以及可能接受的答案中提供的CodeProject链接。
分割输入字符串后,您可以迭代words
并替换与列表中的任何内容匹配的内容(使用swearWords.Contains(word)
进行检查)或者只是检测是否存在任何匹配
var anySwearWords = words.Intersect(swearWords).Any();
答案 4 :(得分:3)
您可以将“myString”拆分为IEnumerable类型,然后对它们使用“Overlaps”吗?
http://msdn.microsoft.com/en-us/library/bb355623(v=vs.90).aspx
(P.S。好久不见......)
编辑:刚刚在我之前的回答中发现错误。