2017-05-07 52 views
1

我在这里获得了此程序来搜索句子中的连词。 我提出的数组:正则表达式匹配器阻止重复搜索字符串

public static final String[] SUB_CONJS = new String[] { 
    "after", "afterwards", "although", "as if", 
    "as long as", "as much as", "as soon as", 
    "as though", "because", "before", "by the time", 
    "even if", "even though", "if", "in order that"... 
    //some more  
}; 

正如你可以看到有repititions如"if""as if"

我使用的匹配搜索它们:

String toSearch = "(?i)\\b(" + String.join("|", SUB_CONJS) + ")\\b"; 
Pattern pattern = Pattern.compile(toSearch); 
Matcher matcher = pattern.matcher(text); 
int count = 0; 
while (matcher.find()) count++; 

例如,如果我将"as if"代入text,count等于2,因为匹配器同时搜索到"if""as if"。有没有方法可以解决问题?谢谢

+1

这将不会编译。没有静态的'Pattern.matcher()'方法。永远不要重新输入代码,总是复制/粘贴到StackOverflow编辑器中。 –

+3

这应该不会发生,因为''如果''如果之前''如果''在正则表达式中'',因此它应该消耗潜在的'好像'在文本中,并且应该防止'if'匹配这样的文本。可能你得到了你的SUB_CONJS数组部分,这些部分比其他部分更具体。你可以尝试使用'contains'方法对这个数组进行排序。如果字符串A包含字符串B,则A应该放在数组B之前。 – Pshemo

回答

1

正如Pshemo写道,您的代码示例在测试字符串"as if":1匹配时返回所需的结果。

这是因为"if"不是"as if"的前缀。实际上,除了Pshermo之外,不要紧,"if""as if"出现在您的正则表达式中并不重要,因为它们不是彼此的前缀。

如果您将"as"添加到以“as”开头的其他条款前面的列表中,则此问题变得更加复杂。在这种情况下,正则表达式实际上“消耗”了“as”,而不考虑可能的更长的匹配。

这是通过相应的排序搜索字词搜索之前容易固定:

Comparator<String> prefixesLast = (s1, s2) -> { 
    if (s1.startsWith(s2)) return -1; 
    if (s2.startsWith(s1)) return 1; 
    return s1.compareTo(s2); 
}; 

,或者使它更简单,通过串为了以防秩序,但下降:

Comparator<String> descending = (s1, s2) -> return s2.compareTo(s1); 

使用排序列表来产生你的正则表达式应该确保总能找到最长的匹配。