在句子中计算单词的正则表达式

7
public static int getWordCount(String sentence) {
    return sentence.split("(([a-zA-Z0-9]([-][_])*[a-zA-Z0-9])+)", -1).length
         + sentence.replaceAll("([[a-z][A-Z][0-9][\\W][-][_]]*)", "").length() - 1;
}

我的意图是计算一个句子中单词的数量。这个函数的输入是一个长句子,最多可能有255个单词。

  1. 单词内可以使用连字符或下划线
  2. 该函数只应计算有效单词,即特殊字符不应被计入。例如,&&&& 或 #### 不应被视为单词。

上述正则表达式运行良好,但当单词内出现连字符或下划线时,例如:co-operation,计数返回为2,而不是1。能否有人提供帮助?


3
\w 元字符有什么问题? - Sharon Ben Asher
你从哪里得到这个正则表达式的? - Pshemo
@sharonbn \w 无法匹配连字符,但是 [-\w] 可以。或者在上述情况下使用 (\w+(-?\w+)*) 或类似语法。 - dhke
分割是一项相当昂贵的操作。 - Willem Van Onsem
这不是错误,更像是不好的风格。[[a-z][A-Z][0-9][\\W][-][_]][a-zA-Z0-9\\W\\-_]相同,后者更容易阅读(并且可以看出由于a-zA-Z0-9_\W的组合,此正则表达式将匹配每个字符,这可能不是您想要的)。另外,([-][_])*(-_)*相同。 - Pshemo
显示剩余2条评论
4个回答

10

请勿使用代价较高的操作.split.replaceAll,请使用常数内存使用的方法。

根据您的要求,您似乎正在寻找以下正则表达式:

[\w-]+

接下来,您可以使用 这种方法 来计算匹配的次数:

public static int getWordCount(String sentence) {
    Pattern pattern = Pattern.compile("[\\w-]+");
    Matcher  matcher = pattern.matcher(sentence);
    int count = 0;
    while (matcher.find())
        count++;
    return count;
}

在线 jDoodle 演示

这种方法在内存使用上更加稳定:分割时,程序会构建一个数组,但实际上这个数组基本上没什么用处,因为你永远不会检查数组的内容。

如果你不想让单词以连字符开头或结尾,可以使用以下正则表达式:

\w+([-]\w+)*

Pshemo,谢谢,你的表达式对我很有效。 - neena

3
这部分代码 ([-][_])* 是错误的。符号[xyz]的意思是“方括号内的任何一个字符”(请参见http://www.regular-expressions.info/charclass.html)。因此,你只允许恰好出现字符-和字符_,而且顺序不能颠倒。

修正你的代码组即可解决问题:

[a-zA-Z0-9]+([-_][a-zA-Z0-9]+)*

而且它可以进一步简化,使用\w来实现

\w+(-\w+)*

因为\w匹配0..9A..Za..z_ (http://www.regular-expressions.info/shorthand.html),所以你只需要添加-

2

如果您可以使用Java 8:

long wordCount = Arrays.stream(sentence.split(" ")) //split the sentence into words   
.filter(s -> s.matches("[\\w-]+")) //filter only matching words
.count();

0

使用Java 8

public static int getColumnCount(String row) {
    return (int) Pattern.compile("[\\w-]+")
        .matcher(row)
        .results()
        .count();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接