查找Java 8时尚中的最大单词数

时间:2019-03-14 10:17:42

标签: java java-8 functional-programming java-stream

需要找到短语中每个句子的最大单词数。句子用?.!符号分隔。

我几乎已经完成了这项任务,但是我坚持以纯Java 8的方式来完成它,您能帮我吗?

public static void main(String[] args) {
    assert solution("We test coders. Give us a try?") == 4;
    assert solution("Forget  CVs..Save time . x x") == 2;
    assert solution("Some some! time . x x") == 2;
}

public static int solution(String S) {
    return Arrays.stream(S.split("[.!?]"))
            .map(String::trim)
            .filter(s -> !s.isEmpty())
            .max(Comparator.comparingInt(o -> o.split(" ").length))
            .map(s -> s.split(" "))
            .flatMap(...); // <-- what to do here?

}

4 个答案:

答案 0 :(得分:4)

我将从Java 9开始使用

// preparation, these can be static final variables
Pattern sentence = Pattern.compile("[^.?!]+"), word = Pattern.compile("\\w+");

int maxWordsPerSentence = sentence.matcher(string).results()
    .mapToInt(s -> (int)word.matcher(s.group()).results().count())
    .max().orElse(0);

流式传输预期的匹配很简单,因为现在,我们不需要过滤空字符串,因为不匹配的流将正确报告零计数。

您可以使用this answer中的results()实现在Java 8中使用类似的逻辑。您只需要将代码更改为

int maxWordsPerSentence = results(sentence.matcher(string))
    .mapToInt(s -> (int)results(word.matcher(s.group())).count())
    .max().orElse(0);

改为调用static方法。

答案 1 :(得分:2)

Pattern p = Pattern.compile("[.!?]");
System.out.println(p.splitAsStream(s)
                    .mapToInt(str -> (int) Arrays.stream(str.split(" "))
                                               .filter(x -> !x.trim().isEmpty())
                                               .count())
                    .max()
                    .orElse(0));

从Java-11开始使用Predicate::not,这将更具可读性:

Pattern p = Pattern.compile("[.!?]");
System.out.println(p.splitAsStream(s)
                    .mapToInt(str -> (int) Arrays.stream(str.split(" "))
                                               .map(String::trim)
                                               .filter(Predicate.not(String::isEmpty))
                                               .count())
                    .max()
                    .orElse(0));

答案 2 :(得分:2)

只需用"\\s+"分隔单词(因此您将忽略多个空格字符)。然后从max()获取IntStream的值。

Arrays.stream(str.split("[.!?]"))
      .map(String::trim)
      .filter(s -> !s.isEmpty()) 
      .mapToInt(s -> s.split("\\s+").length)
      .max()
      .orElse(0);

@Holger提出的最新答案:

Arrays.stream(str.split("\\s*+(?:[.!?]\\s*+)+"))
      .mapToInt(s -> s.split("\\s+").length)
      .max()
      .orElse(0);

还有另一种实用的样式方法(只是为了好玩)。我怀疑您是否需要它:)

Stream.of(str)
      .map(splittingBy("\\s*+(?:[.!?]\\s*+)+"))
      .flatMap(Arrays::stream)
      .map(splittingBy("\\s+"))
      .mapToInt(arr -> arr.length)
      .max()
      .orElse(0);

...

static Function<String, String[]> splittingBy(String regex) {
    return str -> str.split(regex);
}

答案 3 :(得分:1)

您快到了。您无需将空格分开两次:您只需映射到词组中的单词数,然后使用IntStream.max

" "分隔是不够的,因为您可能有多个连续的空格(例如您的示例...Forget CVs...),因此可以使用\\s+分隔一个或多个空白字符。

return Arrays.stream(S.split("[.!?]")) // split into sentences
    .map(String::trim) 
    .filter(s -> !s.isEmpty()) // get rid of empty sentences
    .mapToInt(s -> s.split("\\s+").length) // map to number of words in each sentence
    .max() // get the max (OptionalInt)
    .orElse(0); // if there are no sentences, the result is zero