2016-08-08 8 views
0

私はテキストトークナイザに取り組んでいます。 ICUは、この機能を持つC++ライブラリのほんの数少ないライブラリの1つで、おそらく最も優れたライブラリです。私はそれを使いたいと思います。 私はBreakIteratorについてのドキュメントを見つけましたが、1つの問題があります:どのように句読点を残しておきますか?ICUを使用してテキストを単語リストに分割する

#include "unicode/brkiter.h" 

#include <QFile> 

#include <vector> 

std::vector<QString> listWordBoundaries(const UnicodeString& s) 
{ 
    UErrorCode status = U_ZERO_ERROR; 
    BreakIterator* bi = BreakIterator::createWordInstance(Locale::getUS(), status); 

    std::vector<QString> words; 

    bi->setText(s); 
    for (int32_t p = bi->first(), prevBoundary = 0; p != BreakIterator::DONE; prevBoundary = p, p = bi->next()) 
    { 
     const auto word = s.tempSubStringBetween(prevBoundary, p); 
     char buffer [16384]; 
     word.toUTF8(CheckedArrayByteSink(buffer, 16384)); 
     words.emplace_back(QString::fromUtf8(buffer)); 
    } 

    delete bi; 

    return words; 
} 

int main(int /*argc*/, char * /*argv*/ []) 
{ 
    QFile f("E:\\words.TXT"); 
    f.open(QFile::ReadOnly); 

    QFile result("E:\\words.TXT"); 
    result.open(QFile::WriteOnly); 

    const QByteArray strData = f.readAll(); 
    for (const QString& word: listWordBoundaries(UnicodeString::fromUTF8(StringPiece(strData.data(), strData.size())))) 
    { 
     result.write(word.toUtf8()); 
     result.write("\n"); 
    } 

    return 0; 
} 

当然のことながら、結果のファイルは次のようになります。私は必要なもの

“ 
Come 

outside 
. 

Best 

if 

we 

do 

not 

wake 

him 
. 
” 

ちょうどの言葉です。これはどうすればできますか?

+0

[ispunct](http://www.cplusplus.com/reference/cctype/ispunct/)の機能についてはどうですか?トークンが1文字で構成されているかどうかを確認してから整数として取り出し、その関数でチェックします。 –

+0

@BiagioFesta:まずはASCII以外の文字(引用符など)がたくさんあります。第2に、非単語は、必ずしも単一文字(例えば、カンマ+スペース+オープニング・クォート)である必要はない。 –

答えて

1

QTライブラリには、charのプロパティをチェックするためのいくつかの便利なメソッドが含まれています。 QChar

確かに、あなたはバッファ からQStringの変数を作成し、出力ベクトルに挿入する前に必要なすべてのプロパティをチェックすることができます。例えば

:私は文字列の最初の文字にアクセスし、それが句読点であるかどうか を確認することができるコード付き

auto token = QString::fromUtf8(buffer); 
if (token.length() > 0 && token.data()[0].isPunct() == false) { 
    words.push_back(std::move(token)); 
} 

。より強固な

何か、私は関数として表現していること:その関数がを返す場合

bool isInBlackList(const QString& str) { 
    const auto len = str.lenght(); 
    if (len == 0) return true; 
    for(int i = 0; i < len; ++i) { 
    const auto&& c = str.data()[i]; 
    if (c.isPunct() == true || c.isSpace() == true) { 
     return true; 
    } 
    } 
    return false; 
} 

、トークンは、ベクターに挿入されるようにしていません。

+0

これはまったく悪い考えではありません。私はここでの利便性のためにQtを使っていますが、ICUとstdlibだけに依存する最終的な解決策を望みます。言い換えれば、ICUだけを使って句読点を確認することはできますか? –

+0

ICUには、そのタイプのメソッドはありません。現時点では、私はREGEX:[Regex Class ICU](http://icu-project.org/apiref/icu4c/classicu_1_1RegexMatcher.html)について考えています。 * isInBlackList *関数を再実装するには、文字列の句読点をチェックするだけです。必要な場合は教えてください。そのようなソリューションを追加して回答を編集します。 –

+0

ありがとうございます。私は今、あなたに迷惑をかけたくない、おそらくよりよい解決策がすぐに登場するだろう。また、正規表現に関するパフォーマンスの予約もあります。 Unicodeコードポイントの 'std :: set'としてブラックリストを実装するのですが、手動でこのリストを埋め込む必要はありません.LOT以外のUnicode文字があります。それらをすべて指定することはできません。 –

関連する問題