топ N самых популярных символов

  • прога (консоль) запрашивает абсолютный путь к файлу
  • после чего у пользователя спрашивает выбрать одно из следующих действий:
  1. топ N наиболее использованных слов (N – ввод с клавиатуры)
  2. топ N наиболее использованных символов (N – ввод с клавиатуры)

1 кое как справился но со 2 беда(

import java.io.*;
import java.util.Scanner;

class wordFreq {
    private static final Scanner in = new Scanner(System.in);
    private static String[] w = null;
    private static int[] r = null;
    public static void main(String[] args) throws FileNotFoundException {
        System.out.println("Absolute path to the file:  ");
        String fileName = in.next();
        System.out.println("Choose one of the following actions: ");
        System.out.println("1) top N most used words ");
        System.out.println("2) top N most used characters");
        System.out.println("3) analytics by words (how many which word occurs in percentage and their number)");
        System.out.println("4) character analytics (how many and how many characters occur in percentage)");
        System.out.println("5) save analytics");
        int number = in.nextInt();
        switch (number) {
            case 1:
            try {
                System.out.println("Enter 'N' value: ");
                int n = in.nextInt();
                w = new String[n];
                r = new int[n];
                FileReader fr = new FileReader(fileName);
                BufferedReader br = new BufferedReader(fr);
                String text = "";
                String sz = null;
                while ((sz = br.readLine()) != null) {
                    text = text.concat(sz);
                }
                String[] words = text.split(" ");
                String[] uniqueLabels;
                int count = 0;
                uniqueLabels = getUniqLabels(words);
                for (int j = 0; j < n; j++) {
                    r[j] = 0;
                }
                for (String l : uniqueLabels) {
                    if ("".equals(l) || null == l) {
                        break;
                    }
                    for (String s : words) {
                        if (l.equals(s)) {
                            count++;
                        }
                    }

                    for (int i = 0; i < n; i++) {
                        if (count > r[i]) {
                            r[i] = count;
                            w[i] = l;
                            break;
                        }
                    }
                    count = 0;
                }
                display(n);
            } catch (Exception e) {
                System.err.println("ERR " + e.getMessage());
            }
            break;
            case 2:

        }
    }

    public static void display(int n){
        for(int k=0; k<n; k++){
            System.out.println("Label :: "+w[k]+"\tCount :: "+r[k]);
        }
    }

    private static String[] getUniqLabels(String[] keys)
    {
        String[] uniqueKeys = new String[keys.length];

        uniqueKeys[0] = keys[0];
        int uniqueKeyIndex = 1;
        boolean keyAlreadyExists = false;

        for(int i=1; i<keys.length ; i++)
        {
            for(int j=0; j<=uniqueKeyIndex; j++)
            {
                if(keys[i].equals(uniqueKeys[j]))
                {
                    keyAlreadyExists = true;
                }
            }

            if(!keyAlreadyExists)
            {
                uniqueKeys[uniqueKeyIndex] = keys[i];
                uniqueKeyIndex++;
            }
            keyAlreadyExists = false;
        }
        return uniqueKeys;
    }


}

Вот то что пока что есть


Ответы (1 шт):

Автор решения: ulxanxv

Существуют иные варианты решения вашей задачи. Используйте Stream API и Regex для этих целей, их должен освоить каждый Java-разработчик так как они подходят для огромного количества повседневных задач

Мой вариант решения вашей задачи:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class Main {

    private static final String WORD_REGEX = "[а-яА-Яa-zA-Z]{2,}";
    private static final String ANY_SYMBOL_REGEX = ".{1}";

    public static void main(String[] args) throws IOException {
        final Scanner scanner = new Scanner(System.in);
        System.out.print("Введите путь к файлу: ");

        final Path fileLocation = Paths.get(scanner.nextLine());
        final String content = getContent(fileLocation);

        if (content == null || content.isEmpty()) {
            System.out.println("Файл пуст");
            return;
        }

        System.out.println(String.format("Файл успешно считан, размер %d байт", Files.size(fileLocation)));

        System.out.println("Пожалуйста, выберите действие:\n\t1.\tТоп N самых частых слов\n\t2.\tТоп N самых частых символов");
        System.out.print("Ваш выбор: ");
        int userChoose = scanner.nextInt();

        System.out.print("Пожалуйста, введите число N: ");
        int limit = scanner.nextInt();

        switch (userChoose) {
            case 1: {
                outputResult(
                        topMostPopular(content, WORD_REGEX, limit)
                );
                break;
            }
            case 2: {
                outputResult(
                        topMostPopular(content, ANY_SYMBOL_REGEX, limit)
                );
                break;
            }
            default: {
                System.out.println("Такого действия не существует!");
            }
        }

        scanner.close();
    }

    private static String getContent(Path fileLocation) {
        try {
            return
                    new String(Files.readAllBytes(fileLocation));
        } catch (IOException e) {
            System.err.println(String.format("Error while read file because %s", e.getMessage()));
            return null;
        }
    }

    private static void outputResult(Map<String, Long> result) {
        int top = 1;
        for (Map.Entry<String, Long> entry : result.entrySet()) {
            System.out.println(String.format("%d место\t \"%s\" / %d повторений", top++, entry.getKey(), entry.getValue()));
        }
    }

    private static Map<String, Long> topMostPopular(String content, String regex, int limit) {
        return splitContentBy(content, regex).stream()
                .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
                .entrySet()
                .stream()
                .sorted(Collections.reverseOrder(Map.Entry.comparingByValue(Long::compareTo)))
                .limit(limit)
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
    }

    private static List<String> splitContentBy(String content, String regex) {
        final List<String> result = new ArrayList<>();
        final Matcher matcher = Pattern.compile(regex)
                .matcher(content);
        while (matcher.find()) {
            // Здесь я удалил привязку к регистру, но если хотите вернуть, то удалите .toLowerCase()
            result.add(matcher.group(0).toLowerCase());
        }

        return result;
    }

}

Стоит обратить внимание на метод topMostPopular(String content, String regex, int limit), так как именно он инкапсулирует логику поиска нужных совпадений в тексте и осуществляет их группировку по уникальности, а также обрезает до нужного размера. Всё остальное это чтение и вывод данных...

За поиск нужных совпадений отвечают переменные WORD_REGEX и ANY_SYMBOL_REGEX.
Первая содержит регулярное выражение для поиска слов (английских и русских, а также минимум 2 символа), а второе для поиска абсолютно любых символов (буквы тоже символ)

P.S. Кстати, при запуске вашей программы и выборе поиска самых популярных слов я почему то получил такой странный лог :/

Label :: -  Count :: 54

Он почему-то посчитал, что знак "-" — это слово

→ Ссылка