2

私はテキストファイルを読んでいて、そのテキストファイルからのユニークな単語のセットをArrayListに保存しています(これを行うためのより良い構造があるかどうかを提案してください)。スキャナーを使用してテキストファイルをスキャンし、次のように区切り文字を ""(スペース)として指定しています。

    ArrayList <String> allWords = new ArrayList <String> ();
    ArrayList <String> Vocabulary = new ArrayList <String> ();
    int count = 0;

    Scanner fileScanner = null;
    try {
        fileScanner = new Scanner (new File (textFile));

    } catch (FileNotFoundException e) {
        System.out.println (e.getMessage());
        System.exit(1);
    }

    fileScanner.useDelimiter(" ");

    while (fileScanner.hasNext()) {

        allWords.add(fileScanner.next().toLowerCase());

        count++;

        String distinctWord = (fileScanner.next().toLowerCase());
        System.out.println (distinctWord.toString());

        if (!allWords.contains(distinctWord)) {

            Vocabulary.add(distinctWord);

        }
    }

そのため、語彙の内容を印刷した後、すべての単語の後にスキップされる単語があります。したがって、たとえば、次のテキストファイルがある場合。

「速い茶色のキツネが怠惰な犬を飛び越える」

印刷された内容は「quickfoxoverlazy」で、エラーが発生します。

Exception in thread "main" java.util.NoSuchElementException
    at java.util.Scanner.throwFor(Unknown Source)
    at java.util.Scanner.next(Unknown Source)
    at *java filename*.getWords(NaiveBayesTxtClass.java:82)
    at *java filename*.main(NaiveBayesTxtClass.java:22)

誰かがこれを修正する方法について私にいくつかの提案をお願いしますか?fileScanner.useDelimiterステートメントとfileScanner.hasNext()ステートメントと関係があると感じています。

4

2 に答える 2

5

hasNext()を1回チェックした後、Scanner#next()を2回呼び出しており、next()の戻り値の1つを無視しています。

(1)で呼び出し、allWordsに追加し
、(2)で再度呼び出して、印刷します。

while (fileScanner.hasNext()) {

    allWords.add(fileScanner.next().toLowerCase()); // **** (1)

    count++;

    String distinctWord = (fileScanner.next().toLowerCase());  // **** (2)
    System.out.println (distinctWord.toString());

    if (!allWords.contains(distinctWord)) {

        Vocabulary.add(distinctWord);

    }
}

解決策:Scanner#next()を1回呼び出し、返された文字列を変数に保存してから、変数をHashSetに追加し、変数を出力します。例えば、

while (fileScanner.hasNext()) {
    String word = fileScanner.next().toLowerCase();
    allWords.add(word); // **** (1)
    count++;
    // String distinctWord = (fileScanner.next().toLowerCase());  // **** (2)
    System.out.println (word);
    vocabularySet.add(word); // a HashSet
}

Scanner#hasNextXXX()安全の一般的なルールは、とへの呼び出しごとに1対1の関係を持つ必要があるということです。Scanner#nextXXX()

于 2012-06-03T00:47:51.940 に答える
2

データ構造についても尋ねたので、次のことができます。

    List<String> allWords = new ArrayList<String>();
    SortedSet<String> Vocabulary = new TreeSet<String>();
    int count = 0;

    Scanner fileScanner = null;
    try {
        fileScanner = new Scanner(new File(textFile));

    } catch (FileNotFoundException e) {
        System.out.println(e.getMessage());
        System.exit(1);
    }

    fileScanner.useDelimiter(" ");

    while (fileScanner.hasNext()) {
        String word = fileScanner.next().toLowerCase();
        allWords.add(word);
        if (Vocabulary.add(word)) {
            System.out.print("+ ");
        }
        System.out.println(word);
    }

ご覧のとおり、変数はインターフェイス (List、SortedSet) によって宣言され、具体的なクラスで実装されます。これは再実装を可能にするだけでなく、関数のパラメーターに特に役立ちます。

于 2012-06-03T01:08:33.170 に答える