Найти максимальное количество слов в моде Java 8 - PullRequest
4 голосов
/ 14 марта 2019

Необходимо найти максимальное количество слов для каждого предложения в фразе. Предложения делятся на ?.! символов.

Я почти выполнил эту задачу, но я застрял, чтобы сделать это чисто в стиле 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 ]

4 голосов
/ 14 марта 2019

Начиная с 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);

Поток по намеченным совпадениям прост, так как теперь нам не нужно фильтроватьпустые строки, так как поток без совпадений будет правильно сообщать нулевой счет.

Вы можете использовать аналогичную логику в Java 8, используя реализацию results() в этот ответ .Вам нужно всего лишь изменить код на

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

, чтобы вместо этого вызывать метод static.

2 голосов
/ 14 марта 2019

Просто разделите слова на "\\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);
}
2 голосов
/ 14 марта 2019
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));

Используя Predicate::not начиная с java-11, это было бы еще более читабельно:

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));
1 голос
/ 14 марта 2019

Вы были почти там.Вам не нужно делить пробелы дважды: вы можете просто сопоставить количество слов в фразе, а затем использовать 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
...