3

このようにすると、いくつかの重複が発生します...

private const string _chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123654987";

public string RandomString(int size)
{
    var random = new Random((int)DateTime.Now.Ticks);
    Thread.Sleep(random.Next(1, 3));

    var buffer = new char[size];

    for (int i = 0; i < size; i++)
    {
        buffer[i] = _chars[random.Next(_chars.Length)];
    }
    return new string(buffer);
}

最初の 100000 リクエストは一意である必要があります。基本的にどのように保証できますか...可能であれば、リストを保持してクエリしたくありません...

4

6 に答える 6

2
  • 35^6 (可能な組み合わせの数) 未満の最大の素数を見つけます。
  • それより小さくて 1 より大きい乱数を選択します。
  • (素数 % (乱数 * 反復インデックス)) を取ります。これは、文字列の基になるものです。
  • 結果を base 35 で表現し、文字列を作成します。

これらの文字列は、100,000 回以上反復しても重複しません。これは、乱数が大きい方の数に対して相対的に素であるためです。キャッシングは必要ありません。

文字列を記録する前にランダムな回数の反復を実行して、より大きな結果スペースを得ることができます。

于 2011-11-30T16:57:09.327 に答える
0

ランダムな文字列の長さが制限されている場合は、GUID を使用するのが最も簡単です。

大まかな実装は次のようになります。

    public string RandomString(int size)
    {
        return Guid.NewGuid()
            .ToString()
            .Replace("-","")
            .Substring(0, size);
    }

それ以上必要な場合は、複数の GUID 文字列を連結できます。

于 2011-11-30T16:50:20.813 に答える
0

int を使用してビット位置を表す場合は、簡単に行うことができます。

int bits=0

...

while(bitCount(bits)!=6) // Write your own bitCount method--or there is probably one on the net
    bits++;

int に 6 ビットあることがわかったので、それらを文字列に変換します。

たとえば、データの場合:

"ABCDEFGHIJKLMNOPQRSTUVWXYZ123654987"

数えて 111111 に達した場合 (最初にヒットしたもの)、「234567」を返します。次は 1011111 で、「134567」が返され、次に「1101111」が返され、「124567」が返されます。(シーケンスが間違っている可能性があります。それは頭のてっぺんから外れています)。

それは常に一意であり、反復はあなたが考えるほど高価ではありませんが、反復するよりも少し賢くなる可能性があります (次の 6 に到達することが数学的に不可能であることがわかった場合は、大きなグループをスキップできます)。 - n がインクリメントする前のビット数を「オン」にするか、6 つの 1 で次の整数を生成するためのより単純なアルゴリズムを考え出すことができます。

于 2011-11-30T16:57:49.563 に答える
0

それらがランダムである必要はなく、一意である必要がある場合、このコードは走行距離タイプの出力を使用して機能します。

public class Class1
{
    List<char> _chars = new List<char>() { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
        'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2','3','4', '5', '6', '7', '8', '9', '0' };
    private static int[] index = new int[6] {0, 0, 0, 0, 0, 0};
    private const int charMax = 35;

    public string UniqueString()
    {
        if (index[5] > charMax)
        {
            IncromentParent(5);
        }

        StringBuilder result = new StringBuilder();
        result.Append(_chars[index[0]]);
        result.Append(_chars[index[1]]);
        result.Append(_chars[index[2]]);
        result.Append(_chars[index[3]]);
        result.Append(_chars[index[4]]);
        result.Append(_chars[index[5]]);

        index[5]++;
        return result.ToString();
    }

    private void IncromentParent(int active)
    {
        if (active == 0)
            throw new Exception("out of numbers");

        int parent = active - 1;
        index[active] = 0;
        index[parent]++;
        if (index[parent] > charMax)
            IncromentParent(parent);
    } 
}

そして、これは単体テストに合格していますが、実行に時間がかかります...

[TestMethod]
public void MyTestMethod()
{
    Class1 target = new Class1();
    List<string> results = new List<string>();

    for (int i = 0; i < 100000; i++)
    {            
        string result = target.UniqueString();

        if (!results.Contains(result))
            results.Add(result);
        else
            Assert.Fail(string.Format("The string '{0}' is already in the list", result));
    }
   Console.WriteLine(results.Count.ToString());
}
于 2011-11-30T19:58:17.607 に答える
0

現在のタイム スタンプ (ミリ秒、マイクロ秒、またはナノ秒) を使用して (乱数を表示する必要がある場合は、逆にするか、桁の順序を変更してください)、タイムスタンプ番号の数字を A ~ Z およびいくつかの基準で 0 ~ 9 文字に置き換えることができる場合があります。 .

そうでなければ、以前に生成された値を保存するキャッシュメカニズムがない場合、ランダムで一意の文字シーケンスを取得できないと思います。

于 2011-11-30T17:03:27.350 に答える
0

以前のすべての値のリストを保持しないでください。カウンターを使うだけ。

ユーザーが値を予測しにくく (推測しにくく) したい場合は、ハッシュ関数を使用して、使用する前にビットをスクランブルします。ただし、単純なカウンターからハッシュへの次の入力を生成します。

于 2011-11-30T16:52:48.563 に答える