繁体   English   中英

如何从C#中的给定字符串生成随机字母数字字符串?

[英]How to generate random alphanumeric string from a given string in C#?

我有一个字符串。 我想通过用一个随机数代替一个数字,从这个字符串中产生一个随机字符串。 小写字母按小写字母和大写字母按大写字母。 和其余字符一样。

我写了下面的代码。 我需要在不同的字符串(字符串长度不超过100个字符)上数百万次调用此方法,这花费了太多时间。

private static string GenerateRandomAlphanumericValue(string input) {
    char[] newStr = new char[input.Length];
    char[] alphaU = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
    char[] alphaL = "abcdefghijklmnopqrstuvwxyz".ToCharArray();
    char[] number = "0123456789".ToCharArray();
    Random random = new Random();
    for (int i = 0; i < input.Length; i++) {
        if (char.IsNumber(input[i])) {

            int index = random.Next(0, number.Length);
            newStr[i] = number[index];
        }
        else if (char.IsUpper(input[i])) {
            int index = random.Next(0, alphaU.Length);
            newStr[i] = alphaU[index];
        }
        else if (char.IsLower(input[i])) {
            int index = random.Next(0, alphaL.Length);
            newStr[i] = alphaL[index];
        }
        else {
            newStr[i] = input[i];
        }
    }

    return string.Join("", newStr);
}

我需要优化代码的帮助,或者有其他方法可以解决问题。

输入: vivEK123 $%〜a

输出: ajrLW854 $%〜w

尝试这个

static char[] alphaU = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
static char[] alphaL = "abcdefghijklmnopqrstuvwxyz".ToCharArray();
static char[] number = "0123456789".ToCharArray();
static Random random = new Random();
static StringBuilder sb = new StringBuilder(100);

private static string GenerateRandomAlphanumericValue(string input)
{
    sb.Clear();
    for (int i = 0; i < input.Length; i++)
    {
        if (char.IsNumber(input[i]))
        {
            int index = random.Next(0, number.Length);
            sb.Append(number[index]);
        }
        else if (char.IsUpper(input[i]))
        {
            int index = random.Next(0, alphaU.Length);
            sb.Append(alphaU[index]);
        }
        else if (char.IsLower(input[i]))
        {
            int index = random.Next(0, alphaL.Length);
            sb.Append(alphaL[index]);
        }
        else
        {
            sb.Append(input[i]);
        }
    }

    return sb.ToString();
}

除了使用数组,您还可以根据字符的ASCII值范围进行随机化。 我也建议使用StringBuilder生成结果字符串。

public class Randomizer{
    private static Random rng = new Random();
    public static string RandomizeString(string input){
        StringBuilder sb = new StringBuilder();
        foreach(char c in input){
            if(Char.IsNumber(c)){
                sb.Append(rng.Next(0,10));
            }
            else if(Char.IsLower(c)){
                sb.Append((char)rng.Next(97,123));
            }
            else if(Char.IsUpper(c)){
                sb.Append((char)rng.Next(65,91));
            }
            else{
                sb.Append(c);
            }
        }
        return sb.ToString();
    }
}

注意: az是ASCII 97-122AZ是ASCII 65-90 ,而0-9只是转换为字符串的整数。

这样会更有效率。 我不确定执行时间:

       private static string GenerateRandomAlphanumericValue(string input)
        {
            string newStr = "";
            string alphaU = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            string alphaL = "abcdefghijklmnopqrstuvwxyz";
            string number = "0123456789";
            Random random = new Random();
            for (int i = 0; i < input.Length; i++)
            {
                if (char.IsNumber(input[i]))
                {

                    int index = random.Next(0, number.Length);
                    newStr  += number[index];
                }
                else if (char.IsUpper(input[i]))
                {
                    int index = random.Next(0, alphaU.Length);
                    newStr += alphaU[index];
                }
                else if (char.IsLower(input[i]))
                {
                    int index = random.Next(0, alphaL.Length);
                    newStr += alphaL[index];
                }
                else
                {
                    newStr += input[i];
                }
            }

            return newStr;
        }

一般原则是尽可能多地移出循环并在循环内使用最便宜的技术。

随机只需要构造一次。

StringBuilder是将单个获取的字符移动到字符串中的更有效的方法之一。 而且,它只需要构造一次(但是会带来线程安全问题)。

数组索引是替换链逻辑的一种快速方法,但由于只有三个范围,因此可能不是最快的方法。 if >= && <=乘以三可能更快。)

IsUpper等人可能会对它的性能产生重大影响。 它们必须考虑通用类别Lu,Ll或Nd中的所有Unicode代码点。

private static readonly Random random = new Random();
private static readonly StringBuilder sb = new StringBuilder(100);

// min and max are the replacement range for indexing Char.
private static readonly Char[] min = new Char[Char.MaxValue + 1];
private static readonly Char[] max = new Char[Char.MaxValue + 1];

static UserQuery()
{
    foreach (var range in new[] { 
        (min: 'A', max: 'Z'), 
        (min: 'a', max: 'z'), 
        (min: '0', max: '9') })
    {
        for (var c = range.min; c <= range.max; c++)
        {
            min[c] = range.min;
            max[c] = range.max;
        }
    }
}

private static String GenerateRandomAlphanumericValue(String input)
{
    sb.Clear();
    foreach (var c in input)
    {
        sb.Append((Char)random.Next(min[c], max[c]));
    }
    return sb.ToString();  
}

以下代码来自Bahrom的答案,其中包含对原始代码和Bahrom的代码的注释更改:

//moving out the static initialization cut down the execution time drastically
//since now there's no need repeatedly create these for each execution.
static char[] alphaU = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
static char[] alphaL = "abcdefghijklmnopqrstuvwxyz".ToCharArray();
static char[] number = "0123456789".ToCharArray();
static Random random = new Random();
//moving out Random constructor also remove duplicate result if using identical input
//in close sequence
static char[] temp = new char[100]; //tiny edge compared to using StringBuilder
private static string GenerateRandomAlphanumericValue2(string input)
{            
    for (int i = 0; i < input.Length; i++)
    {
        if (input[i] < '0' || input[i] > 'z')
        //exploit the fact that number, upper case and lower case letter
        //are located between 0 and lower-case z, so anything outside it is
        //left as they are
        {
            temp[i]=(input[i]);
        }
        else if (input[i] <= '9') //no need to check for >='0' again
        {
            temp[i]=(number[random.Next(10)]);
            //using constant size instead of calling length
        }
        else if (input[i] >= 'A' && input[i] <= 'Z')
        {
            temp[i]=(alphaU[random.Next(0, 26)]);
        }
        else if (input[i] >= 'a') //no need to check for <='z' again
        {
            temp[i]=(alphaL[random.Next(0, 26)]);
        }
        else
        {
            temp[i]=(input[i]);
        }
    }

    return new string(temp, 0, input.Length);

}

现在,尽管对Bahrom优雅地使用StringBuilder和IsNumber,IsNumber,IsUpper和IsLower进行了难以理解的优化,但是当对100万个包含0到100个字符的字符串运行时,您的代码大约需要7秒,而Bahrom仅需要7秒大约需要2.5秒,而我的代码需要不到2秒的时间。 这是因为StringBuilder已经针对字符串操作进行了非常优化,并且IsNumber,IsUpper和IsLower确实必须考虑Unicode数字和字母,但是在执行简单return (c >= '0' && c <= '9');之前,它们的实现仅需要两个if来检查字符是否为Latin和Ascii return (c >= '0' && c <= '9'); 因此,如果您想保持代码的可读性,请坚持使用Bahrom的实现。 仅在确实需要压缩最后一个性能(处理数亿个字符串?)的情况下才使用我的

temp声明放回内部,代码是并行友好的,尽管我只是不能更快地执行,因为声明temp over-over-over或使用对象池模式的开销比并行加速要多。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM