我想要一个5个字符的字符串,由从集合[a-zA-Z0-9]中随机选取的字符组成。

用JavaScript实现这一点的最佳方法是什么?


当前回答

//可以将7更改为2以获得更长的结果。让r=(Math.random()+1).toString(36).substring(7);console.log(“随机”,r);

注:上述算法有以下缺点:

它将生成0到6个字符之间的任何字符,这是因为字符串化浮点时会删除尾随零。这在很大程度上取决于用于字符串化浮点数的算法,这非常复杂。(请参阅论文“如何准确打印浮点数字”。)根据实现的不同,Math.random()可能会产生可预测的(“看起来随机”但不是真正随机的)输出。当需要保证唯一性或不可预测性时,生成的字符串不适合。即使它产生了6个统一的随机、不可预测的字符,由于生日悖论,在只产生了大约50000个字符串之后,你也可以看到重复的字符。(平方英尺(36^6)=4656)

其他回答

如果您无法键入字符集,使用String.fromCharCode和范围内的Math.random可以在任何Unicode代码点范围内创建随机字符串。例如,如果您想要17个随机藏文字符,可以输入ranstr(17,0xf00,0xfff),其中(0xf00,0xff)对应于藏文Unicode块。在我的实现中,如果不指定代码点范围,生成器将输出ASCII文本。函数ranchar(a,b){a=(a==未定义?0:a);b=(b===未定义?127:b);return String.fromCharCode(Math.floor(Math.random()*(b-a)+a));}函数transtr(len,a,b){a=a||32;var结果=“”;对于(var i=0;i<len;i++){结果+=ranchar(a,b)}返回结果;}//以下是随机Unicode块的一些示例console.log('拉丁语基本块:'+transtr(10,0x000,0x007f))console.log('拉丁语-1增补块:'+transtr(10,0x080,0x0ff))console.log('货币符号块中:'+transtr(10,0x20a0,0x20cf))console.log('在类字母符号块中:'+transtr(10,0x2100,0x214f))console.log('在Dingbats块中:'+transtr(10,0x2700,0x27bf))

随机unicode字符串

此方法将返回一个随机字符串,其中包含任何受支持的unicode字符,这不是OP要求的100%,而是我想要的:

function randomUnicodeString(length){
    return Array.from({length: length}, ()=>{
        return String.fromCharCode(Math.floor(Math.random() * (65536)))
    }).join('')
}

根本原因

这是谷歌搜索“随机字符串javascript”时的最高结果,但OP只要求a-zA-Z0-9。

这是对doubletap优秀答案的改进。原文有两个缺点,在这里予以解决:

首先,正如其他人所提到的,它很有可能产生短字符串或甚至空字符串(如果随机数为0),这可能会破坏您的应用程序。这里有一个解决方案:

(Math.random().toString(36)+'00000000000000000').slice(2, N+2)

其次,原始和上述解决方案都将字符串大小N限制为16个字符。下面将为任何N返回大小为N的字符串(但请注意,使用N>16不会增加随机性或降低冲突概率):

Array(N+1).join((Math.random().toString(36)+'00000000000000000').slice(2, 18)).slice(0, N)

说明:

选取[0,1)范围内的随机数,即介于0(含)和1(不含)之间。将数字转换为以36为基数的字符串,即使用字符0-9和a-z。用零填充(解决第一个问题)。去掉前导“0.”前缀和额外的填充零。重复字符串足够多次,使其中至少有N个字符(通过将空字符串与用作分隔符的较短随机字符串连接)。从字符串中精确切割N个字符。

进一步思考:

此解决方案不使用大写字母,但在几乎所有情况下(并非双关语)都无关紧要。原始答案中N=16时的最大字符串长度是用Chrome测量的。在Firefox中,N=11。但正如所解释的,第二种解决方案是关于支持任何请求的字符串长度,而不是添加随机性,因此没有太大的区别。至少在Math.random()返回的结果均匀分布的情况下,所有返回的字符串返回的概率相等(无论如何,这不是加密强度随机性)。并非所有可能的大小为N的字符串都可以返回。在第二种解决方案中,这是显而易见的(因为较小的字符串只是被复制),但在原始答案中,这也是正确的,因为在转换为base-36时,最后几位可能不是原始随机位的一部分。具体来说,如果您查看Math.random().toString(36)的结果,您会注意到最后一个字符不是均匀分布的。同样,在几乎所有的情况下,这都无关紧要,但我们从随机字符串的开头而不是结尾对最终字符串进行切片,这样短字符串(例如N=1)就不会受到影响。

更新:

下面是我想出的另外两个功能性风格的单行程序。它们与上述解决方案的不同之处在于:

他们使用一个明确的任意字母表(更通用,适用于要求大写和小写字母的原始问题)。长度为N的所有字符串返回的概率相等(即字符串不包含重复)。它们基于map函数,而不是toString(36)技巧,这使得它们更加简单易懂。

所以,说你选择的字母表是

var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

那么这两个是等价的,因此您可以选择对您更直观的:

Array(N).join().split(',').map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');

and

Array.apply(null, Array(N)).map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');

编辑:

我似乎认为qubyte和Martijn de Milliano提出了类似于后者的解决方案(很好!),但我不知怎么错过了。因为它们一眼看上去不那么短,所以我还是把它放在这里,以防有人真的想要一行:-)

此外,在所有解决方案中,将“new Array”替换为“Array”,以节省更多字节。

生成10个字符长的字符串。长度由参数设置(默认值为10)。

function random_string_generator(len) {
var len = len || 10;
var str = '';
var i = 0;

for(i=0; i<len; i++) {
    switch(Math.floor(Math.random()*3+1)) {
        case 1: // digit
            str += (Math.floor(Math.random()*9)).toString();
        break;

        case 2: // small letter
            str += String.fromCharCode(Math.floor(Math.random()*26) + 97); //'a'.charCodeAt(0));
        break;

        case 3: // big letter
            str += String.fromCharCode(Math.floor(Math.random()*26) + 65); //'A'.charCodeAt(0));
        break;

        default:
        break;
    }
}
return str;
}

你可以使用coderain。这是一个根据给定模式生成随机代码的库。使用#作为大写和小写字符以及数字的占位符:

var cr = new CodeRain("#####");
console.log(cr.next());

还有其他占位符,如A表示大写字母或9表示数字。

可能有用的是,调用.next()将始终为您提供唯一的结果,因此您不必担心重复。

这里是一个生成唯一随机代码列表的演示应用程序。

完全披露:我是《代码雨》的作者。