LINQ を使用して、表現力を高めることができます。
これを使用するにusing System.Linq
は、コードの先頭に があることを確認してください。
仮定して
source
は格納されたターゲット パターンです。
test
テストする文字列です。
それからあなたはすることができます
public static bool IsValid(string source, string test)
{
return test != null
&& source != null
&& test.Length == source.Length
&& test.Where((x,i) => source[i] != x).Count() <=2
}
失敗した瞬間に false を終了するショートカット バージョンもあり、残りの文字列の繰り返しを節約します。
public static bool IsValid(string source, string test)
{
return test != null
&& source != null
&& test.Length == source.Length
&& !test.Where((x,i) => source[i] != x).Skip(2).Any();
}
コメントで要求されたように、これがどのように機能するかについての簡単な説明
C# では、文字列を文字の配列として扱うことができます。これは、Linq メソッドを使用できることを意味します。
test.Where((x,i) => source[i] != x)
これは、テスト内の各文字に対して Where のオーバーロードを使用しx
、文字i
に割り当てられ、インデックスに割り当てられます。ソースの位置 i にある条件文字が x と等しくない場合、結果に出力されます。
Skip(2)
これにより、最初の 2 つの結果がスキップされます。
Any()
結果が残っている場合は true を返し、そうでない場合は false を返します。linq はこれが false である瞬間に実行を延期するため、関数は残りの文字列を評価するのではなく終了します。
次に、「!」をプレフィックスとして付けることで、テスト全体を否定します。これ以上結果がない場所を知りたいことを示します。
部分文字列として一致させるには、正規表現のバックトラッキングと同様に動作する必要があります...
public static IEnumerable<int> GetMatches(string source, string test)
{
return from i in Enumerable.Range(0,test.Length - source.Length)
where IsValid(source, !test.Skip(i).Take(source.Length))
select i;
}
public static bool IsValid(string source, IEnumerable<char> test)
{
return test.Where((x,i) => source[i] != x).Skip(2).Any();
}
更新の説明
Enumerable.Range(0,test.Length - source.Length)
これにより、0 から test.Length - source.Length までの一連の数値が作成されます。長さが短くなると答えが無効になるため、テストのすべての文字から開始してチェックする必要はありません。
私から....
基本的に、i を割り当ててコレクションを反復処理し、毎回現在の値にします。
where IsValid(source, !test.Skip(i).Take(source.Length))
結果をフィルター処理して、インデックス i から始まり (したがってスキップ)、source.Length 文字 (したがって、テイク.
私を選択
私を返す
これは、一致するテストのインデックスに対して列挙可能なものを返します。それらを抽出するには、
GetMatches(source,test).Select(i =>
new string(test.Skip(i).Take(source.Length).ToArray()));