0

我正在处理的问题是,如果结尾在特定列表中,我需要删除该结尾。

即假设列表是:

{ical, ic,ion,ogy} //the actual list is a handful of elements (almost ~20)

我需要做的是,当我遇到这样的句子时:

Hello world, this sentence is magic. Because we will talk about Biology.

它将减少为:

Hello world, this sentence is **mag** . Because we will talk about **Biol** .

最简单的方法是遍历句子中的单词,并检查每个结尾是否与列表中的元素匹配……但这非常昂贵。

有没有更简单的方法来实现上述目标?

***** 还 *****

你可以用一个大的正则表达式来做到这一点:

(?<=([a-zA-Z]))(ic|ical|ics|raphy|raphic|raphical|ion|ions|ional|ive|ivity|ity|ities|ische|ischen|ischer|isches|ogy|ogic|ogical|omy|omic|omics|omical)(?=(\b))
4

3 回答 3

4

简单的方法:

构建输入字符串的正则表达式并将该正则表达式的所有出现替换为空。

正则表达式将采用以下形式:

(a|b|c)\\b

(a|b|c)匹配a,bc.
\\b是单词边界,表示单词的结尾。

代码:

String[] arr = {"ical", "ic", "ion", "ogy"};
String input = "Hello world, this sentence is magic. Because we will talk about Biology.";
String regex = "(" + arr[0];
for (String s: arr)
   regex += "|" + s; // using Pattern.quote(s) instead of s here would be safer
regex += ")\\b";
input = input.replaceAll(regex, "");
System.out.println(input);

印刷:

Hello world, this sentence is mag. Because we will talk about Biol.

更复杂的方法:

建立一个你的后缀的trie,但相反

从后面处理字符串。

如果你得到一个单词的开头,则在 trie 中查找下一个字符,如果在 trie 中找到匹配项,则将它们切断。

最后使用StringBuilderandStringBuilder.reverse()可以有效地执行此操作。

例子:

鉴于:

ical, ic, ion, ogy

您的尝试将如下所示:

          .
         /|\
      y // \\ l
       /n| |c\
      .  . .  .
     g| o| |i |a
      .  . X  .
     o| i|    |c
      X  X    .
              |i
              X

X是终止节点(后缀的结尾),.是非终止节点)

输入:

John Biology.

逆向处理...

过程:"."

不是一句话,只是添加到输出中。

输出 ="."

过程:"Biology"

根有一个y孩子,所以我们移动到那个节点。
该节点有一个g孩子,所以我们继续。
该节点有一个o孩子,所以我们继续。然后我们到达了一个终止节点,所以丢弃处理过的字符并打印单词的其余部分。

输出:".loiB"

过程:" "

不是一句话,只是添加到输出中。

输出 =".loiB "

过程:"John"

根有一个n孩子,所以我们移动到那个节点。
该节点没有h子节点,因此我们停止并输出处理后的字符以及单词的其余部分(即输出整个单词)。

输出 =".loiB nhoJ"

反向,给我们:"John Biol."

于 2013-10-14T13:59:33.473 回答
1

我不知道这是否比循环更有效(我怀疑是这样),但为什么不使用带有 replaceAll() 的正则表达式来去除它们结尾的单词。

\b 标签确保只捕获单词结尾。

public class TestRegEx {

public static final String SENTENCE = "Hello world, this sentence is magic. Because we will talk about Biology. Physical. Reunion.";
public static final String PATTERN = "(ic|ogy|ical|ion)\\b";

public static void main(String[] args) {

     System.out.println(SENTENCE.replaceAll(PATTERN, ""));
    }
} 

我从中得到的输出是:

你好世界,这句话是mag。因为我们将谈论Biol。物理。重来。

希望有帮助。

于 2013-10-14T14:18:03.633 回答
0

如果您想要检查的结尾数量有限,您可以为每个结尾生成一个正则表达式。这应该允许有效检查结尾是否发生,您不需要拆分句子并且可以在一行中进行替换。

遗憾的是,我的 Java 正则表达式知识还不够好,我无法即时构建所需的正则表达式,但你可以看看。但是那里有很多很好的教程

于 2013-10-14T13:59:14.723 回答