2

パターンに基づいて単純な文字列を生成しようとしています。
私の考えは、正規表現を使用して単純な置換を行うことでした。私は簡単な方法から始めました:

private static string parseTemplate(string template)
{
    return Regex.Replace(template, @"(\[d)((:)?([\d]+)?)\]", RandomDigit());
}

private static string RandomDigit()
{
    Random r = new Random();
    return r.Next(0, 9).ToString();
}

これが今のところ行うことは[d]、のようなグループ[d:3]をランダムな数字と見なされるものに置き換えることです。
残念ながら、すべてのグループが同じ数字に置き換えられます。たとえばtest [d][d][d:3]、メソッドを配置すると、 が返されtest 222ます。
のように、あらゆる場所で異なる数字を取得したいと思いtest 361ます。

私が持っている2番目の問題は、長さを処理する方法です:

現時点では、必要なすべての桁を指定する必要がありますが、指定して同じ出力を取得[d]する方が簡単です。[d:3]

Fareというプロジェクトがあることは知っていますが、このライブラリなしでこれを行いたいと思います

今のところ、私は のみを検索しますが[d]、この方法はうまく機能しますか?たとえば[s]、特殊文字やその他の種類のパターンなど、他のグループを追加しても問題はありません。

編集1

提案されたように、次のように Random を静的変数に変更しました。

private static string parseTemplate(string template)
    {
        return Regex.Replace(template, @"(\[d)((:)?([\d]+)?)\]", RandomDigit());
    }

    private static Random r = new Random();

    private static string RandomDigit()
    {
        return r.Next(0, 9).ToString();
    }

問題は、コードを次のように呼び出すときです。

Console.WriteLine(parseTemplate("test [d:2][d:][d]"));
Console.WriteLine(parseTemplate("test [d:2][d:][d]")); 

このような出力が得られます

test 222
test 555

次のような出力が必要です(たとえば):

test 265
test 962

その問題は、Regex.Replace誰が私を一度だけ呼び出すかだと思いますRandomDigit

4

3 に答える 3

3

あなたの最初の問題について:new Random()呼び出すと、関数を呼び出すたびに同じ値でシードされます-静的Randomメンバー変数を一度初期化してから戻りますr.Next(0,9).ToString();

編集:

あなたのコメントに答えて、次のようなデリゲートで MatchEvaluator を使用してみてください (未テスト):

static string RandomReplacer(Match m)
{
    var result = new StringBuilder();
    foreach (char c in m.ToString())
        result.Append(c == 'd' ? RandomDigit() : c);
    return result.ToString()
}

private static string parseTemplate(string template)
{
    return Regex.Replace(template, @"(\[d)((:)?([\d]+)?)\]", new MatchEvaluator(RandomReplacer));
}

次に、このアプローチを拡張[d:3]して MatchEvaluator で照合および解析し、2 番目の問題を解決できます。

于 2013-01-18T10:05:45.287 に答える
1
private static string GenerateMask(string mask)
{
    StringBuilder output = new StringBuilder();
    for (int i = 0; i < mask.Length; i++)
    {
        if (mask[i] == 'd' && mask[i - 1] != '\\')
        {
            int quantifier = 1;

            if (mask[i + 1] == ':')
                Int32.TryParse(mask[i + 2].ToString(), out quantifier);

            output.Append(GetRandomDigit(quantifier));
            i += 2;
        }
        else
        {
            if(mask[i] != '\\')
            output.Append(mask[i]);
        }
    }

    return output.ToString();
}

private static string GetRandomDigit(int length)
{
    Random random = new Random();
    StringBuilder output = new StringBuilder();
    while (output.Length != length)
        output.Append(random.Next(0, 9));
    return output.ToString();
}

主に楽しみのためにまとめたカスタムアルゴリズムがあり、実装は次のとおりです。

Console.WriteLine(GenerateMask(@"Hey Da\d, meet my new girlfrien\d she's d:2"));
//Output: Hey Dad, meet my new girlfriend she's 44
于 2013-01-18T10:48:39.540 に答える
1

以下は、長さ (グループ 4 から読み取った) を使用して、ランダムな数字の文字列を生成します[d:3]MatchEvaluator

static string ReplaceSingleMatch(Match m)
{
    int length;
    if (!int.TryParse(m.Groups[1].Value, out length))
        length = 1;
    char[] chars = new char[length];
    for (int i = 0; i < chars.Length; i++)
        chars[i] = RandomDigit()[0];
    return new string(chars);
}

これを次のように呼び出すことができます。

private static string parseTemplate(string template)
{
    return Regex.Replace(template, @"\[d(?::(\d+))?\]", ReplaceSingleMatch);
}

その後、文字列ではなくRandomDigit1 つの文字列を返すように変更したり、複数の文字を取得して返すように変更したりすることができます。charint

于 2013-01-18T10:31:03.187 に答える