如何编写一个返回长度为6个字符的唯一字符串的方法?

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个请求必须是唯一的,我该如何保证这一点呢?如果可能的话,我不想维护一个列表并对其进行查询...


7
你必须缓存它才能使用。这就是随机性的奇妙之处。 - Daniel A. White
@DanielA.White - 你不是指关于随机性的那个...戴上墨镜...随意的随机事情吗? - Polynomial
你想要独特的还是随机的?它们非常不同。 - Sign
需要涉及到随机性吗?Interlocked.Increment(ref last).ToSting("000000")就可以完成任务了... - Marc Gravell
我知道这听起来有点挖苦,但数字1-100,000是独一无二的,可以最多由六个字符组成(000001)- 您只需要记住您发出的最后一个号码即可。 - K. Bob
我需要独特的字符串...这是我第一次看到Interlocked,我会去了解它。 - Serdar
6个回答

2
  • 找出小于35^6(可能的组合数)的最大质数。
  • 选择一个小于该质数但大于1的随机数。
  • 取(您的质数%(您的随机数*迭代索引))。 这是您从中构建字符串的基础。
  • 用35进制表示结果,并创建您的字符串。

这些字符串在100,000次迭代中不会重叠,因为您的随机数与较大的数字是相对质数。 不需要缓存。

在记录字符串之前,您可以运行随机数量的迭代,以获得更大的结果空间。


这听起来很不错,但它并不能运行。检查算法,但我认为你对相对质性的假设是无效的。 - Ben Voigt

0

不要保留所有先前值的列表,只需使用计数器。

如果您想使值对用户更不可预测(可猜测),请在使用它们之前使用哈希函数来混淆位。但仍然从简单计数器生成哈希的下一个输入。


这听起来不错...我会先看看Interlocked...然后可能对计数器值进行哈希处理... - Serdar

0

你可以使用当前时间戳(毫秒、微秒或纳秒)(如果需要显示随机性,可以将其反转或更改数字顺序),并根据某些条件将时间戳数字中的数字替换为A-Z和0-9字符。

否则,如果您没有任何缓存机制来存储先前生成的值,我认为您无法获得随机且唯一的字符序列。


0
如果您的随机字符串可能的长度是有限的,那么最简单的方法是使用GUID(全局唯一标识符):
一个简单的实现可能是:
    public string RandomString(int size)
    {
        return Guid.NewGuid()
            .ToString()
            .Replace("-","")
            .Substring(0, size);
    }

如果您需要更长的字符串,可以将多个GUID字符串连接在一起。


好的观点 - 独特的是整个字符串,对吧。你能想到一种捕获它的方法吗?取最后n个字符而不是前n个字符是否足够? - Jon Egerton
2
GUID不是唯一的。可能值的范围非常大,因此在随机选择两个值时很不可能得到相同的值两次。 - dtb
问题是:它需要是6个字符长。 - Serdar
1
@JonEgerton:一旦你减小可能值的范围,机率就会变得更高。无论你是从一个更大的可能值范围内计算这些值,都不会有影响。 - dtb
考虑到可能的6个字符字符串数量(如果我的数学有误请纠正我),只有36^6种可能的字母数字6个字符字符串,即仅有2176782336个可能的值。一旦您使用了这么多,您肯定会重复。我建议使用GUID并冒险! - Jon Egerton
显示剩余6条评论

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”(我可能记错了顺序,这只是我脑海中的想法)。

它总是独一无二的,而且迭代并不像你想象的那么昂贵,尽管你可能可以比仅仅迭代更聪明(如果你发现在n增加之前到达下一个6个“on”位数字在数学上是不可能的,你可以跳过大的组,或者你可以想出一个更直接的算法来生成下一个具有6个1的整数。


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());
}

非常感谢您...但我还需要一些随机性...字符串必须是不确定的...我想我会使用时间跨度,并将其与一些内容混合。 - Serdar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接