【问题标题】:Regular expression for counting words in a sentence计算句子中单词的正则表达式
【发布时间】:2015-09-01 04:40:10
【问题描述】:
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. 函数应该只计算有效的单词意味着不应该计算特殊字符,例如。 &&&& 或 #### 不应算作一个单词。

上面的正则表达式工作正常,但是当连字符或下划线出现在单词之间时,例如:合作,返回为2的计数应该是1。有人可以帮忙吗?

【问题讨论】:

  • 哇,这是迄今为止我见过的最糟糕的串联之一。
  • 元符号 \w 有什么问题?
  • 你从哪里得到这个正则表达式?
  • @sharonbn \w 与 hypen 不匹配,但 [-\w] 当然可以。或者在上述(\w+(-?\w+)*) 或类似情况下。
  • 拆分是一项相当昂贵的操作。

标签: java regex


【解决方案1】:

不要使用 .split.replaceAll 这两个非常昂贵的操作,请使用内存使用量恒定的方法。

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

[\w-]+

接下来可以使用this approach来统计匹配数:

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;
}

online jDoodle demo.

这种方法适用于(更多)常量内存:拆分时,程序构造一个数组,这基本上是无用的,因为你从不检查数组的内容。

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

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

【讨论】:

  • Pshemo,谢谢你,你的表达对我来说很好
【解决方案2】:

这部分([-][_])*是错误的。符号[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),所以您只需添加-

【讨论】:

    【解决方案3】:

    如果你可以使用 java 8:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-29
      • 1970-01-01
      • 2019-01-24
      • 1970-01-01
      • 1970-01-01
      • 2021-11-26
      • 2013-11-08
      • 1970-01-01
      相关资源
      最近更新 更多