我想创建一个Messenger应用程序,并且想根据某些关键字过滤传入的String。我计划使用的语言是Java,但我也可以使用Groovy。
关键字列表在文件或csv中的某个位置将是静态的。
关键字列表的大小最大为100个字(绝不会使用超过100个关键字)
传入的字符串最大为200个字节(UTF-8)
我已经看到很多帖子说使用关键字过滤字符串已经过时了。我打算做的应用程序很简单,所以我不想弄乱nlp。
关键字可以是正则表达式或普通单词。
我知道有很多方法可以做到这一点,但是我想要最快的方法。我读过一种不错的方法是使用HashMap,但我不知道如何将它与正则表达式快速组合。
例如,输入字符串可以是:
String example = "I want to gamble and drink vodka all day"
关键字列表将包含:
DRUGS
VODKA.?
GAMBLE
应过滤示例字符串,因为它包含关键字列表中的至少1个单词
编辑*
在一些回答指出使用正则表达式很慢之后,我想找到一个没有正则表达式的好的解决方案。
不使用正则表达式的一种方法是将关键字放入集合中,将传入的字符串拆分为一个数组,然后在该数组上进行迭代,并检查集合中是否包含任何数组字。
在某些情况下,这将不起作用。例如,某人可以输入“我整天喜欢赌博和喝酒”。这将不匹配。
这就是我认为正则表达式是进行单词过滤的唯一方法的原因之一...
答案 0 :(得分:2)
只要您有足够的时间进行预处理,以下方法就会有效:
多字符串搜索
搜索多个字符串(针)将按字符处理输入(干草堆),并跳过将永远不会与任何指定单词匹配的部分。它不仅限于单词边界,而且经常根据干草堆的长度执行超线性运算。
最受欢迎的算法是Aho-Corasick,您可以在stringsearchalgorithms中找到一些经过良好测试的算法
DFA-Regular-Expression-Search
使用正则表达式进行搜索的DFA(确定性有限自动机)引擎逐个字符地处理输入(干草堆)并更新引擎自动机,它从不跳过任何部分,因此永远不会在线性运行时间短的情况下执行。 / p>
正则表达式搜索的主要优点是您可以轻松指定模式而不是单词。主要缺点是预处理时间(最坏情况是图案长度的指数)。前一段时间,我花了几分钟甚至几个小时来等待复杂的正则表达式编译。
您可以在patternsearchalgorithms或brics上找到正则表达式搜索
答案 1 :(得分:1)
一种解决方案(肯定不是最快,但也许足够好)是将列表中的每个条目都视为正则表达式,并将所有正则表达式与|
一起加入以仅对单个正则表达式find()
执行matcher
。
Pattern pattern = Pattern.compile("DRUGS|VODKA.?|GAMBLE");
Matcher matcher = pattern.matcher(input);
boolean result = matcher.find();
答案 2 :(得分:0)
尝试使用正则表达式查找完全匹配的单词:
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SoRegex {
// The static set of keywords.
static final Set<String> keywords = Set.of("DRUGS", "VODKA", "GABMBLE");
public static void main(String[] args) {
// Construct a regular expression that matches any of the keywords anywhere. Use
// word boundaries '\b'.
StringBuilder sb = new StringBuilder("^.*(\\b").append(String.join("\\b|\\b", keywords)).append("\\b).*$");
Pattern p = Pattern.compile(sb.toString());
String input = "I want to gamble and drink vodka all day";
// Convert the input to uppercase since the keywords are uppercase.
Matcher matcher = p.matcher(input.toUpperCase());
System.out
.println(String.format("input '%s' matches pattern '%s': %b", input, p.toString(), matcher.matches()));
}
}
输出:
input 'I want to gamble and drink vodka all day' matches pattern '^.*(\bGABMBLE\b|\bDRUGS\b|\bVODKA\b).*$': true
其他类型的关键字留给读者练习。