Как найти общее количество слов, общее количество гласных, общее количество специальных символов в текстовом файле с использованием Java 8 - PullRequest
2 голосов
/ 25 марта 2019

У меня есть текстовый файл, и я хочу проверить
- общее количество слов в файле
- общее количество гласных в файле
- всего специальный символ в файле

Используя Java 8 Streams.

Я хочу выводить как Карту за одну итерацию, если это возможно, т.е.

{"totalWordCount":10,"totalVowelCount":10,"totalSpecialCharacter":10}

я попробовал ниже код

    Long wordCount=Files.lines(child).parallel().flatMap(line -> Arrays.stream(line.trim().split(" ")))
                            .map(word -> word.replaceAll("[^a-zA-Z]", "").toLowerCase().trim())
                            .filter(word -> !word.isEmpty())
                            .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())).values().stream().reduce(0L, Long::sum)

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

1 Ответ

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

Если бы нам нужно было только подсчитать специальные символы и гласные, мы могли бы использовать что-то вроде этого:

Map<String,Long> result;
try(Stream<String> lines = Files.lines(path)) {
    result = lines
        .flatMap(Pattern.compile("\\s+")::splitAsStream)
        .flatMapToInt(String::chars)
        .filter(c -> !Character.isAlphabetic(c) || "aeiou".indexOf(c) >= 0)
        .mapToObj(c -> "aeiou".indexOf(c)>=0? "totalVowelCount": "totalSpecialCharacter")
        .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
}

Сначала мы сливаем поток строк в поток слов, затем в поток символов,сгруппировать их по типу.Это работает гладко, так как «специальный символ» и «гласный» являются взаимоисключающими.В принципе, уплощение к словам могло бы быть опущено, если бы мы просто расширили фильтр, чтобы пропустить символы пробела, но здесь это помогает получить решение для подсчета слов.

Поскольку слова - это другой тип сущностичем символы, подсчет их в одной и той же операции не так прост.Одно из решений состоит в том, чтобы ввести псевдосимвол для каждого слова и посчитать его, как и другие символы в конце.Поскольку все действительные символы положительные, мы можем использовать -1 для этого:

Map<String,Long> result;
try(Stream<String> lines = Files.lines(path)) {
    result = lines.flatMap(Pattern.compile("\\s+")::splitAsStream)
        .flatMapToInt(w -> IntStream.concat(IntStream.of(-1), w.chars()))
        .mapToObj(c -> c==-1? "totalWordCount": "aeiou".indexOf(c)>=0? "totalVowelCount":
                Character.isAlphabetic(c)? "totalAlphabetic": "totalSpecialCharacter")
        .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
}

Это добавляет категорию "totalAlphabetic" в дополнение к другим в карту результатов.Если вы не хотите этого, вы можете вставить шаг .filter(cat -> !cat.equals("totalAlphabetic")) между шагами mapToObj и collect.Или используйте фильтр, как в первом решении до шага mapToObj.

В качестве дополнительного примечания, это решение выполняет больше работы, чем необходимо, потому что оно разбивает входные данные на строки, что не является необходимым, как мы можемтрактовать разрывы строк так же, как и другие пробелы, то есть как границу слова.Начиная с Java 9, мы можем использовать Scanner для задания:

Map<String,Long> result;
try(Scanner scanner = new Scanner(path)) {
    result = scanner.findAll("\\S+")
        .flatMapToInt(w -> IntStream.concat(IntStream.of(-1), w.group().chars()))
        .mapToObj(c -> c==-1? "totalWordCount": "aeiou".indexOf(c)>=0? "totalVowelCount":
                Character.isAlphabetic(c)? "totalAlphabetic": "totalSpecialCharacter")
        .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
}

Это разделит ввод на слова в первую очередь без особой обработки переносов строк. Этот ответ содержит совместимую с Java 8 реализацию Scanner.findAll.

Приведенные выше решения рассматривают каждый символ, который не является ни пробелом, ни алфавитом, как «специальный символ».Если ваше определение «специального символа» отличается, адаптировать решения не должно быть слишком сложно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...