2013-10-14 63 views
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** . 

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

有没有更简单的方法来达到上述目的?

*另*

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

(?<=([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)) 
+0

你的句子会有多大?如果您的结尾列表仅包含〜20个元素,性能不应该太差。 – arshajii

+0

网络I/O操作,数据库查询非常昂贵。你所描述的操作可能会比较贵一些。如果需要多次,这可能是您希望缓存的结果......但无论如何,我认为解决问题的方法并不比您提议的方法更有效。 – scottb

+0

在任何情况下,它似乎至少比正则表达式匹配近20个结局... – Guillaume

回答

4

简单的方法:

构建输入字符串的regular expression和更换什么,正则表达式的所有出现。

正则表达式将是以下形式:

(a|b|c)\\b 

(a|b|c)比赛abc
\\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中找到匹配项,则将其切断。

最后使用StringBuilderStringBuilder.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."

0

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

可悲的是,我的java正则表达式知识不够好,我可以在飞行中建立所需的正则表达式,但你可以看看。但有很多good tutorials out there

+0

由于这个答案只是指出OP在正确的方向,而不是回答这个问题,它可能更适合作为评论。 – Dukeling

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。物理学。 Reun。

希望有所帮助。

相关问题