5

Java で BreakIterator クラスを使用して、段落を文に分割しています。これは私のコードです:

public Map<String, Double> breakSentence(String document) {
    sentences = new HashMap<String, Double>();
    BreakIterator bi = BreakIterator.getSentenceInstance(Locale.US);
    bi.setText(document);

    Double tfIdf = 0.0;
    int start = bi.first();
    for(int end = bi.next(); end != BreakIterator.DONE; start = end, end = bi.next()) {
        String sentence = document.substring(start, end);

        sentences.put(sentence, tfIdf);
    }

    return sentences;
}

問題は、段落にタイトルや数字が含まれている場合です。たとえば、次のようになります。

「1,200行のコードを書くことで問題を解決しようとしているロバーツ教授。」

私のコードが生成するものは次のとおりです。

sentences :
Prof
Roberts trying to solve a problem by writing a 1
200 lines of code

タイトルと数字のピリオドのため、1 つの文ではなく。

Javaでタイトルと数字を処理するためにこれを修正する方法はありますか?

4

2 に答える 2

6

これはちょっと難しい状況です。私は粘着性のある解決策を考え出しましたが、それでもうまくいきます。私自身 Java は初めてなので、経験豊富なベテランがこれを編集したりコメントしたりして、より専門的なものにしたい場合は、ぜひ見栄えを良くしてください。

基本的に、Dr. Prof. Mr. Mrs. などの単語が存在するかどうかを確認して確認する必要があるものに、いくつかの制御手段を追加し、それらの単語が存在する場合は、そのブレークをスキップして次のブレークに移動します (元の開始位置) 次の終了を探します (できれば、Dr. または Mr. などの後に終了しないもの)

あなたがそれをすべて見ることができるように、私は私の完全なプログラムを含めています:

import java.text.BreakIterator;
import java.util.*;

public class TestCode {

    private static final String[] ABBREVIATIONS = {
        "Dr." , "Prof." , "Mr." , "Mrs." , "Ms." , "Jr." , "Ph.D."
    };

    public static void main(String[] args) throws Exception {

        String text = "Prof. Roberts and Dr. Andrews trying to solve a " +
                      "problem by writing a 1.200 lines of code. This will " +
                      "work if Mr. Java writes solid code.";

        for (String s : breakSentence(text)) {
              System.out.println(s);
        }
    }

    public static List<String> breakSentence(String document) {

        List<String> sentenceList = new ArrayList<String>();
        BreakIterator bi = BreakIterator.getSentenceInstance(Locale.US);
        bi.setText(document);
        int start = bi.first();
        int end = bi.next();
        int tempStart = start;
        while (end != BreakIterator.DONE) {
            String sentence = document.substring(start, end);
            if (! hasAbbreviation(sentence)) {
                sentence = document.substring(tempStart, end);
                tempStart = end;
                sentenceList.add(sentence);
            }
            start = end; 
            end = bi.next();
        }
        return sentenceList;
    }

    private static boolean hasAbbreviation(String sentence) {
        if (sentence == null || sentence.isEmpty()) {
            return false;
        }
        for (String w : ABBREVIATIONS) {
            if (sentence.contains(w)) {
                return true;
            }
        }
        return false;
    }
}

これが行うことは、基本的に 2 つの開始点を設定することです。元の開始点 (使用したもの) は同じことを行っていますが、文字列を文にする準備ができているように見えない限り、temp start は移動しません。それは最初の文を取ります:

"Prof."

そして、それが奇妙な単語のために壊れたかどうかを確認します (つまり、その壊れの原因となった可能性のある文に Prof. Dr. または w/e が含まれていますか)。次のチャンクが戻ってくるのを待ちます。私のもう少し手の込んだ文では、次のチャンクにも、区切りを台無しにする奇妙な単語があります。

"Roberts and Dr."

そのチャンクを取得し、Dr. が含まれているため、文の 3 番目のチャンクに続きます。

"Andrews trying to solve a problem by writing a 1.200 lines of code."

壊れた 3 番目のチャンクに到達し、誤って壊れた可能性のある奇妙なタイトルがない場合、一時的な開始 (まだ最初にある) から現在の終了まで開始し、基本的に 3 つの部分すべてを結合します。

現在、一時的な開始を現在の「終了」に設定して続行します。

私が言ったように、これはあなたが望むものを手に入れるための魅力的な方法ではないかもしれませんが、誰も志願しませんでした。

于 2013-06-18T05:05:29.063 に答える
0

大文字で始まるProf. Robert場合にのみ s が分割されるようです。Roberts

Roberts小文字で始まる場合、分割されrません。

BreakIteratorだから...それが期間を扱う方法だと思います。

ドキュメントをさらに読むと、この動作を変更する方法が説明されると確信しています。

于 2013-06-18T02:41:36.443 に答える