です。
まず、指定された値のセットから特定の長さのすべての組み合わせを生成するメソッドを作成します。文字列の生成にのみ関心があるので、string
は不変であるという事実を利用できます(P.D.2参照)。再帰関数を実装するのが非常に簡単になり、次の理由が考えられます。
static IEnumerable<string> GetAllCombinations<T>(
ISet<T> set, int length)
{
IEnumerable<string> getCombinations(string current)
{
if (current.Length == length)
{
yield return current;
}
else
{
foreach (var s in set)
{
foreach (var c in getCombinations(current + s))
{
yield return c;
}
}
}
}
return getCombinations(string.Empty);
}
このメソッドがどのように機能するかを慎重に検討します。それを理解するための小さな事例を手で手にしてください。
は今、かつて我々はすべての可能な組み合わせを生成する方法を知って、文字列を構築するのは簡単です:指定された文字列内のワイルドカードの数うち
- 図:これは私たちの組み合わせの長さになります。
- すべての組み合わせについて、各文字をワイルドカードが出現する文字列に挿入します。
public static IEnumerable<string> GenerateCombinations<T>(
this string s,
IEnumerable<T> set,
char wildcard)
{
var length = s.Count(c => c == wildcard);
var combinations = GetAllCombinations(set, length);
var builder = new StringBuilder();
foreach (var combination in combinations)
{
var index = 0;
foreach (var c in s)
{
if (c == wildcard)
{
builder.Append(combination[index]);
index += 1;
}
else
{
builder.Append(c);
}
}
yield return builder.ToString();
builder.Clear();
}
}
そして、我々は終わった:
[OK]を、ちょうどそれを行うことができます。使用法は次のようになります。
var set = new HashSet<int>(new[] { 1, 2, 3, 4 });
Console.WriteLine(
string.Join("; ", "[email protected]@d".GenerateCombinations(set, '@')));
そして案の定、出力は次のようになります。これは最もパフォーマンスや効率的な実装
a1bc1d; a1bc2d; a1bc3d; a1bc4d; a2bc1d; a2bc2d; a2bc3d;
a2bc4d; a3bc1d; a3bc2d; a3bc3d; a3bc4d; a4bc1d; a4bc2d;
a4bc3d; a4bc4d
ですか?おそらくそれは読めるものではなく、保守可能なものです。あなたが会議ではない特定のパフォーマンス目標を持っていない限り、うまく動作し、理解しやすいコードを記述します。
P.D.私はすべてのエラー処理と引数の検証を省略しました。
P.D.2:組み合わせの長さが大きい場合は、GetAllCombinations
の連結文字列はお勧めできません。その場合、GetAllCombinations
はIEnumerable<IEnumerable<T>>
を返し、ImmutableStack<T>
を実装し、それをstring
の代わりに組み合わせバッファとして使用します。