Java 8 Streams |Среднее количество слов для строк в текстовом файле - PullRequest
0 голосов
/ 13 мая 2018

Я пытаюсь выполнить упражнение на потоках и столкнулся со следующей проблемой:

У меня есть текстовый файл, и я хочу вычислить среднее количество слов в строке.Может кто-нибудь сказать мне, правильно ли мое мышление?Вот какой-то псевдокод, который, как мне кажется, должен был бы выполнить один раз реализованный трюк:

double wordCount(String filepath){
  return Files.lines(Paths.get(filepath))
                      // make a wordarray of the line
                      // average the size of every wordarray with something like that
                          (collect(Collectors.averagingDouble())

Может кто-нибудь помочь мне с этим?

Как я могу преобразовать строку в массив слов String?

Как получить размер этого массива?

Ответы [ 4 ]

0 голосов
/ 14 мая 2018

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

Если вы хотите получить количество слов, рассмотрите простой метод, считая только слова

private static final Pattern WORD = Pattern.compile("\\w+");
public static int wordCount(String s) {
    int count = 0;
    for(Matcher m = WORD.matcher(s); m.find(); ) count++;
    return count;
}

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

Files.lines(Paths.get(filePath)).mapToInt(YourClass::wordCount).average().orElse(0)

В Java 9 вы можете переписать метод wordCount, чтобы использовать поток, подобный

private static final Pattern WORD = Pattern.compile("\\w+");
public static int wordCount(String s) {
    return (int)WORD.matcher(s).results().count();
}

Но цикл, вероятно, более эффективен, поскольку в нем опущено создание MatchResult экземпляров.

0 голосов
/ 13 мая 2018

2 пропущенных шага:

  • Как мне преобразовать строку в строковый массив слов: split вокруг spaces >> s.split(" ");

  • Как получить размер этого массива: получить его length >> arr.length


  1. Использование специализированной операции на IntStream

    double wordCount(String filepath) {
        try {
            return Files.lines(Paths.get(filepath))
                    .map(s -> s.split(" "))
                    .mapToInt(arr -> arr.length)
                    .average()
                    .orElse(-1.0);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return -1.0;
    }
    
  2. Менее специфичная Collectors операция ( Во избежание повторения проп 1. 1. 1033 *)

    double wordCount2(String filepath) {
        try {
            return Files.lines(Paths.get(filepath))
                    .map(s -> s.split(" "))
                    .map(arr -> arr.length)
                    .collect(Collectors.averagingDouble(Double::new));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return -1.0;
    }
    
0 голосов
/ 14 мая 2018
private static void wordcount(String filePath) throws IOException {
    Path path = Paths.get(Paths.get(filePath).toUri());
    double result = Files.lines(path).map(s -> {
        String trimmed = s.trim();
        if (trimmed.isEmpty()) return 0;
        else return trimmed.split(" ").length;
    }).mapToInt(i -> i.intValue()).average().getAsDouble();

    System.out.println(result);
}
0 голосов
/ 13 мая 2018

Попробуйте это:

 try(Stream<String> lines = Files.lines(Paths.get("src/test.txt"))){

            OptionalDouble average =
                    lines.map(s -> s.split(" "))
                            .mapToInt(s -> s.length)
                            .average();

            System.out.println(average.getAsDouble());
        } catch (IOException e)
        {
            e.printStackTrace();
        }
...