我有一个字符串。我想通过用一个随机数代替一个数字,从这个字符串中产生一个随机字符串。小写字母按小写字母和大写字母按大写字母。还有其他字符。
我写了下面的代码。我需要在不同的字符串上(字符串长度不超过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
答案 0 :(得分:1)
尝试一下
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();
}
答案 1 :(得分:0)
除了使用数组,您还可以根据字符的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();
}
}
注意:a-z
是ASCII 97-122
,A-Z
是ASCII 65-90
,而0-9
只是转换为字符串的整数。
答案 2 :(得分:0)
这效率更高。我不确定执行时间:
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;
}
答案 3 :(得分:0)
一般原理是尽可能多地移出循环,并在循环内使用最便宜的技术。
随机只需构建一次。
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();
}
答案 4 :(得分:0)
以下代码源自Bahrom's answer,其中包含对原始代码和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,IsUpper和IsLower进行了难以理解的优化,但当对一百万个包含0到100个字符的字符串运行时,您的代码大约需要7秒钟,而Bahrom仅需约2.5秒,而我的代码仅需不到2秒。这是因为StringBuilder已经针对字符串操作进行了非常优化,并且IsNumber,IsUpper和IsLower确实必须考虑Unicode数字和字母,但是它们的实现只需要two if's to check if a character is Latin & Ascii,然后再进行简单的return (c >= '0' && c <= '9');
等。因此,如果要保持代码可读性,请坚持使用Bahrom的实现。仅在确实需要压缩最后一个性能(处理数亿个字符串?)的情况下,才使用我的。
将temp
声明放回内部,并且代码是并行友好的,尽管由于反复声明temp
或使用对象池的开销我无法获得更快的执行速度模式不仅仅是并行加速。