このようなものについては、正規表現を使用するよりも、直接的なアプローチを好みます。これにより、文字列全体で最大 1 回のパスが作成され、正規表現よりも効率的になります。
/// Return true if every instance of 'a' in the string is followed by 'b'.
/// Also returns true if there are no instances of 'a' in the string.
/// Returns false if there exists any 'a' that is not followed by 'b'.
public static bool IsTwoCharSequence(string s, char a, char b)
{
if(String.IsNullOrEmpty(s)) return true;
if(s[s.Length - 1] == a) return false; // ends in a, not followed by b. Condition failed.
int index = s.IndexOf(a); // find the first a
while(index != -1)
{
if(s[index + 1] != b) return false; // a not followed by b.
index = s.IndexOf(a, index + 1);
}
return true; // either no a, or all a followed by b.
}
編集:さらに、正規表現内の特殊文字でもある場合、区切り文字を引用する方法について心配する必要はありません。
編集 2: はい、2 つのループですが、各ループが何をしているかを見てください。
String.IndexOf の内部にある内側のループは、渡された文字が見つかるまで文字を反復処理します。IndexOf (while ループの外側の呼び出し) への最初の呼び出しは、文字列の先頭から検索を開始し、後続の呼び出しはそのインデックスから開始し、次の一致または最後まで検索を続けます。全体として、文字列全体で 1 回だけパスを作成しました。
上記の方法と概念が似ている別の方法を次に示しますが、「文字列全体を 1 回だけ反復する」ことがより明示的です。
public static bool IsTwoCharSequence(string s, char a, char b)
{
if (String.IsNullOrEmpty(s)) return true;
bool foundA = false;
foreach (char c in s)
{
if (foundA && c == b)
foundA = false;
else if (foundA)
return false;
else if (c == a)
foundA = true;
}
if (foundA) return false; // 'a' was the last char in the string.
return true;
}