我想过滤一个字符串。
基本上,当有人键入消息时,我希望过滤掉某些单词,如下所示:
用户类型: hey guys lol omg -omg mkdj*Omg*ndid
我希望过滤器运行并且:
输出: hey guys lol - mkdjndid
我需要从ArrayList
包含几个要过滤掉的单词中加载过滤后的单词。现在我正在做,但如果有人输入 zomg或-omg或类似的if(message.contains(omg))
,那将不起作用。
Use replaceAll with a regex built from the bad word:
message = message.replaceAll("(?i)\\b[^\\w -]*" + badWord + "[^\\w -]*\\b", "");
This passes your test case:
public static void main( String[] args ) {
List<String> badWords = Arrays.asList( "omg", "black", "white" );
String message = "hey guys lol omg -omg mkdj*Omg*ndid";
for ( String badWord : badWords ) {
message = message.replaceAll("(?i)\\b[^\\w -]*" + badWord + "[^\\w -]*\\b", "");
}
System.out.println( message );
}
戴夫已经给了你答案,但我会在这里强调声明。如果您使用一个简单的 for 循环来实现您的算法,该循环只是替换过滤词的出现,您将面临一个问题。例如,如果您过滤单词“classic”中的单词 ass 并将其替换为“butt”,则结果单词将是“clbuttic”,这没有任何意义。因此,我建议使用一个单词列表,例如存储在 Linux 中 /usr/share/dict/ 目录下的单词列表,以检查该单词是否有效或需要过滤。我不太明白你想要做什么。
尝试:
input.replaceAll("(\\*?)[oO][mM][gG](\\*?)", "").split(" ")
我遇到了同样的问题并通过以下方式解决了它:
1)有一个谷歌电子表格,其中包含我想要过滤掉的所有单词
2)使用loadConfigs方法直接将google电子表格下载到我的代码中(见下文)
3) 用它们各自的字母替换所有 l33tsp33k 字符
4) 替换句子中除字母外的所有特殊字符
5)运行一个算法,有效地检查字符串中所有可能的单词组合与列表,注意这部分是关键 - 你不想每次都循环遍历整个列表来查看你的单词是否在列表中. 就我而言,我在字符串输入中找到了每个组合,并对照哈希图(O(1) 运行时)对其进行了检查。这样,运行时间相对于字符串输入而不是列表输入增长。
6) 检查该词是否未与好词组合使用(例如,bass 包含*ss)。这也是通过电子表格加载的
6)在我们的例子中,我们也将过滤后的单词发布到 Slack,但您显然可以删除该行。
我们在我们自己的游戏中使用它,它就像一个魅力。希望你们喜欢。
https://pimdewitte.me/2016/05/28/filtering-combinations-of-bad-words-out-of-string-inputs/
public static HashMap<String, String[]> words = new HashMap<String, String[]>();
public static void loadConfigs() {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(new URL("https://docs.google.com/spreadsheets/d/1hIEi2YG3ydav1E06Bzf2mQbGZ12kh2fe4ISgLg_UBuM/export?format=csv").openConnection().getInputStream()));
String line = "";
int counter = 0;
while((line = reader.readLine()) != null) {
counter++;
String[] content = null;
try {
content = line.split(",");
if(content.length == 0) {
continue;
}
String word = content[0];
String[] ignore_in_combination_with_words = new String[]{};
if(content.length > 1) {
ignore_in_combination_with_words = content[1].split("_");
}
words.put(word.replaceAll(" ", ""), ignore_in_combination_with_words);
} catch(Exception e) {
e.printStackTrace();
}
}
System.out.println("Loaded " + counter + " words to filter out");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Iterates over a String input and checks whether a cuss word was found in a list, then checks if the word should be ignored (e.g. bass contains the word *ss).
* @param input
* @return
*/
public static ArrayList<String> badWordsFound(String input) {
if(input == null) {
return new ArrayList<>();
}
// remove leetspeak
input = input.replaceAll("1","i");
input = input.replaceAll("!","i");
input = input.replaceAll("3","e");
input = input.replaceAll("4","a");
input = input.replaceAll("@","a");
input = input.replaceAll("5","s");
input = input.replaceAll("7","t");
input = input.replaceAll("0","o");
ArrayList<String> badWords = new ArrayList<>();
input = input.toLowerCase().replaceAll("[^a-zA-Z]", "");
for(int i = 0; i < input.length(); i++) {
for(int fromIOffset = 1; fromIOffset < (input.length()+1 - i); fromIOffset++) {
String wordToCheck = input.substring(i, i + fromIOffset);
if(words.containsKey(wordToCheck)) {
// for example, if you want to say the word bass, that should be possible.
String[] ignoreCheck = words.get(wordToCheck);
boolean ignore = false;
for(int s = 0; s < ignoreCheck.length; s++ ) {
if(input.contains(ignoreCheck[s])) {
ignore = true;
break;
}
}
if(!ignore) {
badWords.add(wordToCheck);
}
}
}
}
for(String s: badWords) {
Server.getSlackManager().queue(s + " qualified as a bad word in a username");
}
return badWords;
}