DELPHI のワイルドカード比較 (第 5 版)
著者: 李俊宇
電子メール: [email protected] 2003.1.5
DELPHI にはワイルドカード用の既製の関数がないと思っていたのですが、MatchesMask() を見つけました。この機能に出会う前は、暇なときや気が向いた時にカスタム関数を作ってこの機能を実現していました。
プログラムのアルゴリズムはさらに複雑です。まず部分文字列の末尾に「?」を追加します。 *' を使用して、部分文字列を読み取り、部分文字列内のワイルドカード文字の間の文字、つまり部分文字列内の部分文字列を検索し、ソース文字列内を検索して、部分文字列内の部分文字列が含まれているかどうかを確認します。実装にはまだ多くの紆余曲折があり、費用がかかります。この関数は次の関数を実装します。
1.ほとんどの場合、再帰アルゴリズムや MatchesMask() よりも高速である可能性があります。
2.すべてのケースでアスタリスクと疑問符の正しい比較が実装されました。 // これは検証するのに時間がかかる可能性があります。
3.中国語をサポート; // アスタリスクと疑問符は英語である必要があります。
4.大文字と小文字を区別した選択をサポートします。
部分文字列の先頭と末尾にアスタリスクを追加することには違いがあることに注意してください。このアルゴリズムは、スタック上の再帰アルゴリズムを使用して実装された関数に似ているかもしれませんが、実際には再帰プロセスにいくつかの改良が加えられており、ほとんどの場合、どれだけ高速になるかは困難です。 ? 確かに。少なくとも次の推定値があります。ソース文字列が「1111111111」で部分文字列が「*11111112*」など、ワイルドカード比較が部分文字列の検索にのみ使用される場合、再帰アルゴリズムを使用する時間計算量は O(N*M )と書きましたが、この関数は、POS() 関数を数回呼び出す程度の時間計算量に単純化されます。おそらく、DELPHI の POS() は、以下の「Knut-Morris-Pratt (KMP) アルゴリズム」O(N+M) として想像できます。 。再帰的アルゴリズムとの速度の比較は、回数が少ない場合には明らかではありません。ソース文字列に 100 個の連続する 1 があり、サブストリングに 99 個の連続する 1 があり、最後に文字 2 が追加される場合、1000 回のループでテストした後、再帰アルゴリズムよりも数秒速く、MatchesMask() よりも 20 秒速くなります。秒の機能。実際に複数のテストを行った結果、3 つすべてが最も速い場合もありますが、ほとんどの場合、MatchesMask() の方が遅いことがわかり、再帰の速度は大きく異なります。私が作成した関数の速度は平均的である可能性があります。ただ、私が書いた機能はあくまで参考ですので、何か問題が起きても私は責任を負いません。
function isABClikeAX(const abc,ax:widestring):boolean; file://abc はソース文字列、ax はサブ文字列です。
変数
abcstart、axstart、abclength、axlength:integer;
endpartabc、endpartax、subax:ワイド文字列;
一時、abcwww、axwww:整数;
ファイルを開始します:://aaa
温度:=0;
abcスタート:=1;
axstart:=1;
axwww:=1;
abcwww:=1;
abclength:=length(abc);
axlength:=length(ax);
isabclikeax:=true;
while axstart<=axlength do//ソース文字列の長さが部分文字列以上の場合
始まります//bbb
if abcstart> abclength then
始める
(ax[axlength]='*') かつ (axlength=axstart) の場合、isabclikeax:=true
else isabclikeax:=false;//部分文字列がソース文字列より長い場合
壊す;
終わり;
ax[axstart]='?' の場合
始める
inc(axstart);
inc(abcstart);
続く;
終わり;
ax[axstart]='*' の場合
始める
inc(axstart);
温度:=1;
axwww:=axstart;
abcwww:=abcstart;
続く;
終わり;
if not((ax[axstart]='?') または (ax[axstart]='*') )
始まります//ccc
endpartax:=copy(ax,axstart,axlength-axstart+1)+'?*';
subax:=copy(endpartax,1,min(pos('?',endpartax),pos('*',endpartax))-1);
axstart:=axstart+min(pos('?',endpartax),pos('*',endpartax))-1;
endpartabc:=copy(abc,abcstart,abclength-abcstart+1);
if ((pos(subax,endpartabc)<>0) および (temp=1 )) または ((pos(subax,endpartabc)=1) および (temp=0))
始まります//ddd
temp=1 の場合、temp:=0;
abcstart:=abcstart+(pos(subax,endpartabc)+length(subax)-1) ;
終わり//ddd
そうでなければ//ddd
始まります//ddd
(temp=0) かつ (axwww>1) の場合
始める
axstart:=axwww;
abcwww:=abcwww+1;
abcstart:=abcwww;
温度:=1;
続く;
終わり;
isabclikeax:=false;
壊す;
終了;//ddd
終了;//ccc
終わり;//bbb
if (result) and (abcstart<=abclength) and (ax[axlength]<>'*') then isabclikeax:=false;//ソース文字列が部分文字列より長い場合
終わり;//ああ
FUNCTION IsLike(abc,ax:string):boolean file://大文字と小文字を区別する関数
始める
islike:=isABClikeAX(abc,ax);
終わり;
FUNCTION WideCard(abc,ax:string):boolean; file://大文字と小文字を区別しない関数
始める
abc:=大文字(abc);
ax:=大文字(ax);
Widecard:=isABClikeAX(abc,ax);
終わり;
USES MATH に注意してください。MIN() が使用されているため、IF ステートメントを使用して MIN() を置き換えることもできますが、十分に明確ではありません。
正しい洞察を与えてくれた一部のネチズンに感謝し、正しい方向に改訂するのに役立ちました。