我想要一个5个字符的字符串,由从集合[a-zA-Z0-9]中随机选取的字符组成。
用JavaScript实现这一点的最佳方法是什么?
我想要一个5个字符的字符串,由从集合[a-zA-Z0-9]中随机选取的字符组成。
用JavaScript实现这一点的最佳方法是什么?
当前回答
这是肯定的
<script language="javascript" type="text/javascript">
function randomString() {
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
var string_length = 8;
var randomstring = '';
for (var i=0; i<string_length; i++) {
var rnum = Math.floor(Math.random() * chars.length);
randomstring += chars.substring(rnum,rnum+1);
}
document.randform.randomfield.value = randomstring;
}
</script>
其他回答
function generate(length) {
var letters = ["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","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","0","1","2","3","4","5","6","7","8","9"];
var IDtext = "";
var i = 0;
while (i < length) {
var letterIndex = Math.floor(Math.random() * letters.length);
var letter = letters[letterIndex];
IDtext = IDtext + letter;
i++;
}
console.log(IDtext)
}
这是第一个答案的测试脚本(谢谢@csharptest.net)
该脚本运行makeid()100万次,如您所见,5不是一个非常独特的脚本。以10的字符长度运行它是非常可靠的。我已经运行了大约50次,还没有看到重复的:-)
注意:节点堆栈大小限制超过了大约400万,因此您无法运行这500万次,它永远无法完成。
function makeid()
{
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for( var i=0; i < 5; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
ids ={}
count = 0
for (var i = 0; i < 1000000; i++) {
tempId = makeid();
if (typeof ids[tempId] !== 'undefined') {
ids[tempId]++;
if (ids[tempId] === 2) {
count ++;
}
count++;
}else{
ids[tempId] = 1;
}
}
console.log("there are "+count+ ' duplicate ids');
如果任何人对一个一次性分配内存的单行程序(虽然为了方便起见,没有格式化为这样)感兴趣(但请注意,对于小字符串,这实际上无关紧要),下面是如何做到的:
Array.apply(0, Array(5)).map(function() {
return (function(charset){
return charset.charAt(Math.floor(Math.random() * charset.length))
}('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'));
}).join('')
您可以用所需字符串的长度替换5。感谢@AriyaHidayat在本文中提供的解决方案,该解决方案解决了array(5)创建的稀疏数组上的map函数不工作的问题。
"12345".split('').map(function(){return 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.charAt(Math.floor(62*Math.random()));}).join('');
//or
String.prototype.rand = function() {return this.split('').map(function(){return 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.charAt(Math.floor(62*Math.random()));}).join('');};
将生成长度为第一个/调用字符串的随机字母数字字符串
这是对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”,以节省更多字节。