1

約 50/150kb のテキスト ファイルがアップロードされ、多数のフレーズ (~10k) と照合されるプロセスを実装する必要があります。

どのフレーズが具体的に一致するかを知る必要があります。

フレーズは「何とか何とか」または単に「何とか」である可能性があります。つまり、中置一致を含めたくないため、単語の境界を考慮する必要があります。

私の最初の試みは、次のような正規表現のコンパイル済みの大きなリストを作成することでした@"\b{0}\b"(10k のフレーズは一定であるため、複数のドキュメントに対してこの同じリストをキャッシュして再利用できます);

私の最新の非常に高速な PC では、このマッチングに 10 秒以上かかっていますが、これを大幅に短縮したいと考えています。

どうすればこれを達成できるかについてのアドバイスをいただければ幸いです。

乾杯、デイブ

4

2 に答える 2

1

Lucene.Net を使用できます

これにより、テキストの inedx が作成されるため、それに対して非常に迅速なクエリを実行できます。これが「全文索引」です。

この記事では、そのすべてについて説明します。

Lucene.net

このライブラリはもともと Java (Lucene) で書かれていますが、.NET (lucene.net) へのポートがあります。

ステマーを選択するときは、特に注意する必要があります。ステマーは単語の「語根」を取るため、いくつかの類似した単語が一致します (つまり、book と books が一致します)。完全一致が必要な場合は、元の単語を変更せずに返すステマーを使用 (または実装) する必要があります。

インデックスの作成と結果の検索には、同じステマーを使用する必要があります。

また、構文も確認する必要があります。構文が強力すぎて、部分一致や完全一致などが可能になるためです。

このブログもご覧ください。

于 2012-09-13T10:46:04.400 に答える
1

フレーズが持つことができる単語の数に上限があることを気にしない限り、Lucene.NET とシングル フィルターを使用できます。

public class MyAnalyzer : Analyzer
{
    public override TokenStream TokenStream(string fieldName, TextReader reader)
    {       
        return new ShingleFilter(new LowerCaseFilter(new StandardTokenizer(Lucene.Net.Util.Version.LUCENE_29, reader)), 6);
    }
}

このユーティリティ メソッドを使用してアナライザーを実行できます。

public static IEnumerable<string> GetTerms(Analyzer analyzer, string keywords)
{
    var tokenStream = analyzer.TokenStream("content", new StringReader(keywords));
    var termAttribute = tokenStream.AddAttribute<ITermAttribute>();

    var terms = new HashSet<string>();

    while (tokenStream.IncrementToken())
    {
        var term = termAttribute.Term;
        if (!terms.Contains(term))
        {
            terms.Add(term);
        }
    }

    return terms;
}

すべての用語を取得したら、単語リストと交差します。

var matchingShingles = GetTerms(new MyAnalyzer(), "Here's my stuff I want to match");

var matchingPhrases = phrasesToMatch.Intersect(matchingShingles, StringComparer.OrdinalIgnoreCase);

この方法は、正規表現マッチングよりもはるかに高速で、単語の境界を尊重することがわかると思います。

于 2012-09-13T13:20:37.257 に答える