【问题标题】:Random string with no duplicates没有重复的随机字符串
【发布时间】:2013-03-03 11:54:55
【问题描述】:

我正在尝试生成一个没有重复字符的 16 个字符的随机字符串。我认为这不应该太难,但我被困住了。

我使用了 2 种方法,一种用于生成密钥,另一种用于删除重复字符。在 main 中,我创建了一个 while 循环以确保生成的字符串长度为 16 个字符。

我的逻辑有问题,因为它只是弹出 16 个字符的字符串 有重复。就是搞不定。

代码:

public string RemoveDuplicates(string s)
{
    string newString = string.Empty;
    List<char> found = new List<char>();
    foreach (char c in s)
    {
        if (found.Contains(c))
            continue;

        newString += c.ToString();
        found.Add(c);
    }
    return newString;
}

public static string GetUniqueKey(int maxSize)
{
    char[] chars = new char[62];
    chars =
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray();
    byte[] data = new byte[1];
    RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();
    crypto.GetNonZeroBytes(data);
    data = new byte[maxSize];
    crypto.GetNonZeroBytes(data);
    StringBuilder result = new StringBuilder(maxSize);
    foreach (byte b in data)
    {
        result.Append(chars[b % (chars.Length)]);

    }
    return result.ToString();
}

string builder = "";

do
{                       

    builder = GetUniqueKey(16);
    RemoveDuplicates(builder);

    lblDir.Text = builder;
    Application.DoEvents();


} while (builder.Length != 16);

【问题讨论】:

    标签: c# random no-duplicates


    【解决方案1】:

    考虑实现shuffle algorithm,您将使用独特的字符来打乱您的字符串,然后只需选取前 16 个字符。

    您可以就地执行此操作,方法是分配单个 StringBuffer,其中将包含您的初始数据(“abc ....”),并使用 Durstenfeld 的算法版本来改变您的缓冲区,而不是返回前 16 个字符.

    【讨论】:

    • 谢谢!如此简单而优雅。正是我想要的。
    【解决方案2】:

    有很多算法可以解决这个问题。

    一个简单的方法是:

    1. 用可用字符填充字符数组。
    2. 随机排列数组。
    3. 取前 N 个项目(其中 N 是您需要的字符数)。

    示例代码:

    using System;
    
    namespace ConsoleApplication2
    {
        internal class Program
        {
            private static void Main(string[] args)
            {
                var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray();
                Random rng = new Random();
    
                for (int i = 0; i < 10; ++i)
                {
                    string randomString = RandomString(16, chars, rng);
                    Console.WriteLine(randomString);
                }
            }
    
            public static string RandomString(int n, char[] chars, Random rng)
            {
                Shuffle(chars, rng);
                return new string(chars, 0, n);
            }
    
            public static void Shuffle(char[] array, Random rng)
            {
                for (int n = array.Length; n > 1; )
                {
                    int k = rng.Next(n);
                    --n;
                    char temp = array[n];
                    array[n] = array[k];
                    array[k] = temp;
                }
            }
        }
    }
    

    【讨论】:

      【解决方案3】:
      const string chars = 
                     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
      var r = new Random();
      var s = new string(chars.OrderBy(x => r.Next()).Take(16).ToArray());
      

      【讨论】:

        【解决方案4】:

        我使用的是 GUID 生成方法,它本身会生成随机字符串,如果开头出现数字,您可以修改它, 使用下面给出的代码:

        string guid = System.Guid.NewGuid().ToString("N");
                    while (char.IsDigit(guid[0]))
                        guid = System.Guid.NewGuid().ToString("N");
        

        希望对您有所帮助。

        【讨论】:

        • 指南不是随机的。它们可能是唯一的,但它们不是随机的。 .NET 规范中没有任何内容表明 guid 不是唯一的。
        【解决方案5】:

        看看这是否有帮助:

            RandomString()
            {
                string randomStr = Guid.NewGuid().ToString();
                randomStr = randomStr.Replace("-", "").Substring(0, 16);   
                Console.WriteLine(randomStr);
            }
        

        这将返回字母数字字符串。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-12-09
          • 2020-05-13
          • 1970-01-01
          • 1970-01-01
          • 2010-12-07
          相关资源
          最近更新 更多