Словарь создан из текстового файла - contains () всегда возвращает false - PullRequest
0 голосов
/ 06 октября 2018

В настоящее время я занят в небольшом университетском назначении и у меня возникли некоторые проблемы с методом contains () класса словаря, который я реализовал - метод всегда возвращает false.Класс выглядит следующим образом:

public class LocalDictionary {
    private ArrayList<String> wordsSet;

    public LocalDictionary() throws IOException {
        String wordListContents = new String(Files.readAllBytes(Paths.get("words.txt")));

        wordsSet = new ArrayList<>();
        String[] words = wordListContents.split("\n");
        for (int i = 0; i < words.length; i++) {
            wordsSet.add(words[i].toLowerCase());
        }
    }

    public boolean contains(String word) {
        return wordsSet.contains(word.toLowerCase());
    }
}

Файл "words.txt", из которого словарь получает свои слова, доступен по адресу https://raw.githubusercontent.com/dwyl/english-words/master/words_alpha.txt, но вот фрагмент того, как он выглядит:

zinked
zinkenite
zinky
zinkiferous
zinkify
zinkified
zinkifies
zinkifying
zinnia
zinnias
zinnwaldite
zinober
zinsang
zinzar
zinziberaceae

Я убедился, что слова из "words.txt" содержатся в 'wordsSet', но не могу понять, почему метод contains возвращает false для слов, которые отображаются в ArrayList.

Буду признателен за любую помощь.

Ответы [ 3 ]

0 голосов
/ 06 октября 2018

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

public class LocalDictionary {
    private ArrayList<String> wordsSet = new ArrayList<>();

    public LocalDictionary() throws Exception {

        //dont forget to absolute path to here. click righ click to file and copy path
        File file = new File("C:\\Users\\higuys\\IdeaProjects\\try\\src\\words.txt");
        BufferedReader br = new BufferedReader(new FileReader(file));

        String line;
        while ((line = br.readLine()) != null)
            //trim and tolowercase and add to list.
            wordsSet.add(line.trim().toLowerCase());

    }

    public boolean contains(String word) {
        return wordsSet.contains(word.toLowerCase());
    }
}
0 голосов
/ 06 октября 2018

Ваша проблема заключается в неправильном обращении с OS-зависимым разделителем строк, здесь

String[] words = wordListContents.split("\n");

оставляя дополнительные символы в строках вашего словаря.Не все ОС используют «\ n» для разделения строк, поэтому вы должны написать код, чтобы принять это во внимание.

Один из вариантов - позволить Java сказать вам, какой разделитель строк использовать, а затем использовать его:

String lineSeparator = System.getProperty("line.separator");
String[] words = wordListContents.split(lineSeparator);

Хотя проще всего использовать файлы для получения всех строк, что-то вроде:

private List<String> wordsSet1;
private ArrayList<String> wordsSet2;

public TestDictionary(String path) throws IOException {
    // my code:
    wordsSet1 = Files.readAllLines(Paths.get(path));

Используя файлы readAllLines, вы разрешите Java выбрать правильный разделитель строк.

сравните ваш код с моим:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

import save.MyColorFoo;

public class TestDictionary {
    // public static final String TXT_PATH = "src/pkg1/words.txt";
    // TODO: change this to your correct path
    public static final String TXT_PATH = "words.txt";
    private List<String> wordsSet1;
    private ArrayList<String> wordsSet2;

    public TestDictionary(String path) throws IOException {
        // my code:
        wordsSet1 = Files.readAllLines(Paths.get(path));

        // his code
        String wordListContents = new String(Files.readAllBytes(Paths.get(path)));

        wordsSet2 = new ArrayList<>();
        String[] words = wordListContents.split("\n");
        for (int i = 0; i < words.length; i++) {
            wordsSet2.add(words[i].toLowerCase());
        }

    }

    public boolean myContains(String word) {
        return wordsSet1.contains(word.toLowerCase());
    }

    public boolean hisContains(String word) {
        return wordsSet2.contains(word.toLowerCase());
    }

    public static void main(String[] args) {
        try {
            TestDictionary testDictionary = new TestDictionary(TXT_PATH);

            String testWord = "zinky";
            System.out.println("My List contains \"zinky\":  " + testDictionary.myContains(testWord));
            System.out.println("His List contains \"zinky\": " + testDictionary.hisContains(testWord));

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Если выЕсли вы не уверены, что в исходном текстовом файле есть все строчные буквы, а затем нужно их уменьшить, то вы можете использовать Streams, чтобы помочь вам сделать это:

wordsSet1 = Files.readAllLines(Paths.get(path))
        .stream().map(s -> s.toLowerCase())
        .collect(Collectors.toList());
0 голосов
/ 06 октября 2018

Обрежьте каждую строку в цикле перед добавлением.Кажется, после каждого слова в строке есть дополнительное место.

for (int i = 0; i < words.length; i++) {
    wordsSet.add(words[i].toLowerCase());
}

до

for (int i = 0; i < words.length; i++) {
    wordsSet.add(words[i].trim().toLowerCase());
}

Это можно проверить с помощью wordsSet.get(1).length().Согласно вашему файлу первая строка 'aa', но это печатает 3 вместо 2, и это потому, что после каждого слова есть дополнительный пробел, который необходимо обрезать перед добавлением в список.

Нетпроблема с вашим contains() методом.

...