ある種のデータオブジェクト(辞書を考えています)で正規表現のトンをキーとして保持しようとしています。次に、テキストの文字列を取得し、それらと照合して、辞書から実際の値を取得する必要があります。 。大量のデータセットに対してこれを行うための効率的な方法が必要です。
私はC#を使用していますが、どこから始めればよいかわかりません。
ある種のデータオブジェクト(辞書を考えています)で正規表現のトンをキーとして保持しようとしています。次に、テキストの文字列を取得し、それらと照合して、辞書から実際の値を取得する必要があります。 。大量のデータセットに対してこれを行うための効率的な方法が必要です。
私はC#を使用していますが、どこから始めればよいかわかりません。
LINQ を使用しない理由
Dictionary<string, string> myCollection = new Dictionary<string, string>();
myCollection.Add("(.*)orange(.*)", "Oranges are a fruit.");
myCollection.Add("(.*)apple(.*)", "Apples have pips.");
myCollection.Add("(.*)dog(.*)", "Dogs are mammals.");
// ...
string input = "tell me about apples and oranges";
var results = from result in myCollection
where Regex.Match(input, result.Key, RegexOptions.Singleline).Success
select result;
foreach (var result in results)
{
Console.WriteLine(result.Value);
}
// OUTPUT:
//
// Oranges are a fruit.
// Apples have pips.
正規表現が自明な単一文字列ではなく、効率を重視する場合は、それらを単一のNFA (最終状態の値を持つ非決定論的有限状態オートマトン) で表現する必要があります。入力がより一致する可能性がある場合正規表現が 1 つ以上の場合、最終状態には一連の値が必要になります。
この時点で、オートマトンの最適化を検討する準備が整いました。実質的に決定できる場合 (これにより、NFA よりも指数関数的に大きくなる可能性のある DFA が得られます)、必ずそれを実行してください。DFA を取得したら、それを効率的に (そして同型まで一意に) 最小化できます (ただし、最終状態に値があるため、通常のアルゴリズムの明らかな変更が必要です)。
NFA を直接最小化する手法もあります。たとえば、2 つの状態に同じサフィックス セット ({(残りの文字列、値)}) がある場合、それらは同等であり、組み合わせることができます。非巡回 NFA での等価性は、最終状態から始まるハッシュコンシングによって行うことができます。
これに実際に正規表現が必要かどうかはわかりません- trieを使用できます。辞書を表すことは、トライの一般的なアプリケーションです。(「連想配列」の意味ではなく、単語のリストのような辞書を意味していると思います)。
文字列を正規表現と照合して、正規表現の一致を取得することを意味しますか? それとも単なるテキストマッチ?言い換えれば、あなたがしようとしている文字列は、それらの正規表現の 1 つなのか、それとも正規表現を適用するデータなのか?
それが正規表現であり、リストでそれを見つけたい場合、辞書は必要ありません。これらは 2 つの部分のコンテナーです。List または StringCollection を使用して、IndexOf(mytString) を要求することができます。-1 はそこにないことを意味します。
正規表現を複数回使用する予定がある場合は、正規表現オブジェクトをコンパイル済みとして作成し、それを再利用してオーバーヘッドを削減できることに注意してください。
Regex RegexObject = new Regex(Pattern, RegexOptions.Compiled);
このモデルを使用すると、パターン文字列ではなく正規表現オブジェクトを保存するのが最適です。