JavaScript中的随机字母数字字符串?
Posted
技术标签:
【中文标题】JavaScript中的随机字母数字字符串?【英文标题】:Random alpha-numeric string in JavaScript? 【发布时间】:2012-05-30 09:54:04 【问题描述】:在 javascript 中生成随机字母数字(大写、小写和数字)字符串以用作可能唯一的标识符的最短方法(在合理范围内)是什么?
【问题讨论】:
最短路径?这是一个代码高尔夫问题吗? 哈哈,不!这不是谁能将他们的代码打包得最严密的竞赛。我见过一些解决方案将整个字符集列在一个字符串中,这似乎很浪费。只是在寻找比它需要的时间不长的东西。 @Pavel 这就是代码高尔夫...... @Pavel ***.com/questions/1349404/… @neal 删除冗余是一种很好的工程实践,代码高尔夫是编写最少的代码(通常涉及单个字符变量、副作用和其他不良实践)。它们相似但非常不同。 【参考方案1】:我刚刚发现这是一个非常好的和优雅的解决方案:
Math.random().toString(36).slice(2)
关于此实现的说明:
这将生成一个长度介于 0 到 12 个字符之间的字符串,通常为 11 个字符,因为浮点字符串化会删除尾随零。 它不会生成大写字母,只会生成小写字母和数字。 因为随机性来自Math.random()
,所以输出可能是可预测的,因此不一定是唯一的。
即使假设实现是理想的,输出也最多具有 52 位熵,这意味着在生成大约 70M 字符串后,您可以预期会出现重复。
【讨论】:
使用slice(2)
代替substr(2,16)
: jacklmoore.com/notes/substring-substr-slice-javascript
@kimos 不错。解决这个问题的一种方法是再试一次。例如:function rStr() var s=Math.random().toString(36).slice(2); return s.length===16 ? s : rStr();
您的网站繁忙吗?那么有时它会生成一个小于0.000001
的随机数。较小数字的toString()
类似于3.4854687E-7
,您的随机字母数字字符串将是4854687E-7
,它不再是字母数字。这不再符合 OP 的要求
您能解释一下这是如何工作的吗?你为什么将36
传递给toString
?
toString 采用基数参数,即整数转换为字符串的“基数”。我认为最容易掌握的是var a = 5;a.toString(2)
;将以二进制格式返回数字 5,因此 101
。完整文档:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…【参考方案2】:
如果您只想允许特定字符,您也可以这样做:
function randomString(length, chars)
var result = '';
for (var i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];
return result;
var rString = randomString(32, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
这里有一个 jsfiddle 来演示:http://jsfiddle.net/wSQBx/
另一种方法是使用一个特殊的字符串来告诉函数使用什么类型的字符。你可以这样做:
function randomString(length, chars)
var mask = '';
if (chars.indexOf('a') > -1) mask += 'abcdefghijklmnopqrstuvwxyz';
if (chars.indexOf('A') > -1) mask += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
if (chars.indexOf('#') > -1) mask += '0123456789';
if (chars.indexOf('!') > -1) mask += '~`!@#$%^&*()_+-=[]:";\'<>?,./|\\';
var result = '';
for (var i = length; i > 0; --i) result += mask[Math.floor(Math.random() * mask.length)];
return result;
console.log(randomString(16, 'aA'));
console.log(randomString(32, '#aA'));
console.log(randomString(64, '#A!'));
小提琴:http://jsfiddle.net/wSQBx/2/
或者,要使用如下所述的 base36 方法,您可以执行以下操作:
function randomString(length)
return Math.round((Math.pow(36, length + 1) - Math.random() * Math.pow(36, length))).toString(36).slice(1);
【讨论】:
我真的很喜欢第二种方法。我尝试使用它,它似乎有一些问题。从THIS 截图可以看出,它有时会生成不是指定长度的字符串。我将您的randomString(..)
函数放在生成 50 个随机字符串的 for(var i=0;i<50;i++)
循环中,最后一个是三个字符长。我还告诉它像这样向文档写入 50 次:document.write(randomString(8, '#aA!') + "</br>");
@Matthew 这可能是您的浏览器在输出字符串中无意中拾取了一个错误标签。检查输出源,看看里面是否有一些任性的造成了麻烦。
嗯,这里有一个统计错误。 Math.round(Math.random() * (chars.length - 1))
将给出 [0]
和 [chars.length-1]
的一半概率,而不是其余字符,因为分别需要在间隔 [0, 0.5)
和 [chars.length-2+0.5, chars.length-1)
中舍入一个数字,大小为 0.5,而其余字符字符需要大小为 1 的 [index-0.5, index+0.5)
。正确的索引函数应该是:parseInt(Math.random() * chars.length)
,因为排除了 random() 的上限,并且无法达到 chars.length
:w3schools.com/jsref/jsref_random.asp
@Nimphious 请给我你的参考资料。 Math.random()
永远不会返回 1。它的返回值在 [0, 1)
中,这意味着包含 0 而排除 1。以下是四个不同且重要的独立来源:Mozilla:goo.gl/BQGZiG;微软 MSDN (IE):goo.gl/MPuCJM; w3schools:goo.gl/qXrK7P; ***:goo.gl/CUoyIT(num
是1
)和goo.gl/D9az3C 和goo.gl/0mERDq。您假设 1 是 Math.random() 的可能值的来源是什么?因为不是。
我冒昧地修复了代码中的统计错误。因为这是 google 上“随机 javascript 字符串”的最高结果,所以有一个错误的答案是一种耻辱。【参考方案3】:
JAR.JAR.beans 提出的另一种答案
(Math.random()*1e32).toString(36)
通过更改乘数1e32
,您可以更改随机字符串的长度。
【讨论】:
很好的答案,这对我有帮助。使用 1e32 我得到了 19 个字符长的字符串,使用 1e64 我得到了 40 个字符。非常感谢! @BogdanLewis 请注意,不能保证字符串长度。这意味着 1e64 并不总是产生 40 个字符长度的字符串,但它会接近 40。 我明白了!我正在寻找生成长随机字符串(接近 40 个字符)的简单解决方案 好答案。但是,它不会生成大写(大写)字母【参考方案4】:更新: 单行解决方案,随机 20 个字符(字母数字小写):
Array.from(Array(20), () => Math.floor(Math.random() * 36).toString(36)).join('');
或者用lodash更短:
_.times(20, () => _.random(35).toString(36)).join('');
【讨论】:
【参考方案5】:或者根据 Jar Jar 的建议,这是我在最近的一个项目中使用的(克服长度限制):
var randomString = function (len, bits)
bits = bits || 36;
var outStr = "", newStr;
while (outStr.length < len)
newStr = Math.random().toString(bits).slice(2);
outStr += newStr.slice(0, Math.min(newStr.length, (len - outStr.length)));
return outStr.toUpperCase();
;
用途:
randomString(12, 16); // 12 hexadecimal characters
randomString(200); // 200 alphanumeric characters
【讨论】:
【参考方案6】:这样更干净
Math.random().toString(36).substr(2, length)
例子
Math.random().toString(36).substr(2, 5)
【讨论】:
这似乎不适用于长度 > 16 但是你可以做这样的逻辑...... console.log(Math.random().toString(36).substring(2, 15) + Math.random().toString( 36).substring(2, 15)) + Math.random().toString(36).substring(2, 15)); :-)【参考方案7】:我认为以下是允许给定长度的最简单的解决方案:
Array(myLength).fill(0).map(x => Math.random().toString(36).charAt(2)).join('')
这取决于箭头函数语法。
【讨论】:
【参考方案8】:function randomString(len)
var p = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
return [...Array(len)].reduce(a=>a+p[~~(Math.random()*p.length)],'');
总结:
创建一个我们想要的大小的数组(因为 javascript 中没有
range(len)
等效项。 对于数组中的每个元素:从p
中选择一个随机字符并将其添加到字符串中 返回生成的字符串。
一些解释:
[...Array(len)]
Array(len) 或 new Array(len) creates an array with undefined pointer(s)。单线将更难实现。 Spread syntax 方便地定义了指针(现在它们指向未定义的对象!)。
.reduce(
Reduce 数组,在本例中为单个字符串。 The reduce functionality is common in most languages 值得学习。
a=>a+...
我们使用的是arrow function。
a
是 累加器。 在这种情况下,它是我们完成后要返回的最终结果字符串(你知道它是一个字符串,因为 reduce 的第二个参数函数,initialValue 是一个空字符串:''
)。所以基本上:用p[~~(Math.random()*p.length)]
转换数组中的每个元素,将结果附加到a
字符串,完成后给我a
。
p[...]
p
是我们从中选择的字符串。您可以像索引一样访问字符串中的字符(例如,"abcdefg"[3]
给我们"d"
)
~~(Math.random()*p.length)
Math.random()
返回 [0, 1) Math.floor(Math.random()*max)
is the de facto standard for getting a random integer in javascript 之间的浮点数。 ~
是 javascript 中的按位 NOT 运算符。
~~
是一种更短,可以说有时更快,而且绝对更有趣的方式来表达Math.floor(
Here's some info
【讨论】:
虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高答案的长期价值。【参考方案9】:32 个字符:
for(var c = ''; c.length < 32;) c += Math.random().toString(36).substr(2, 1)
【讨论】:
【参考方案10】:使用 lodash:
function createRandomString(length)
var chars = "abcdefghijklmnopqrstufwxyzABCDEFGHIJKLMNOPQRSTUFWXYZ1234567890"
var pwd = _.sampleSize(chars, length || 12) // lodash v4: use _.sampleSize
return pwd.join("")
document.write(createRandomString(8))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
【讨论】:
_.sample()
只返回一个字符。我想你的意思是_.sampleSize()
使用 lodash 生成随机 CSS 十六进制颜色:_.sampleSize("abcdef0123456789", 6).join("")
_.sample 签名在 lodash v4 中更改。
使用_.sampleSize
生成随机字符串不是一个好主意。它只会生成 unique 元素(它永远不会重复一个字符)。这减少了熵。
另外,在上面的例子中,如果length > 62
返回的字符串总是62个字符长,因为chars
的大小。【参考方案11】:
随机字符:
String.fromCharCode(i); //where is an int
随机整数:
Math.floor(Math.random()*100);
把它们放在一起:
function randomNum(hi)
return Math.floor(Math.random()*hi);
function randomChar()
return String.fromCharCode(randomNum(100));
function randomString(length)
var str = "";
for(var i = 0; i < length; ++i)
str += randomChar();
return str;
var RandomString = randomString(32); //32 length string
小提琴:http://jsfiddle.net/maniator/QZ9J2/
【讨论】:
这包括一大堆非字母数字字符。一个例子(我第一次尝试得到的):M&I56aP=H K?<T*, ;0'9_c5Tb
我得到了] 4INBKJ\`_5.(/"__X,,K"\)]
很多字符不可用并被 SO 剥离
空字节 (String.fromCharCode(0)) 在许多语言/数据库/环境中导致各种问题。代码 33-126 产生可见的 ASCII 字符。【参考方案12】:
随机密钥生成器
keyLength 参数是您想要的键的字符长度
function keyGen(keyLength)
var i, key = "", characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var charactersLength = characters.length;
for (i = 0; i < keyLength; i++)
key += characters.substr(Math.floor((Math.random() * charactersLength) + 1), 1);
return key;
keyGen(12)
"QEt9mYBiTpYD"
【讨论】:
【参考方案13】:当我看到这个问题时,我想到了何时必须生成 UUID。我不能相信代码,因为我确信我在 *** 上找到了它。如果您不想要字符串中的破折号,请取出破折号。这是函数:
function generateUUID()
var d = new Date().getTime();
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,function(c)
var r = (d + Math.random()*16)%16 | 0;
d = Math.floor(d/16);
return (c=='x' ? r : (r&0x7|0x8)).toString(16);
);
return uuid.toUpperCase();
小提琴:http://jsfiddle.net/nlviands/fNPvf/11227/
【讨论】:
您当然可以缩短或加长字符串,使其包含任意数量的字符。 这是我最有可能找到代码的地方:***.com/a/8809472/988540【参考方案14】:var randomString = function(length)
var str = '';
var chars ='0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'.split(
'');
var charsLen = chars.length;
if (!length)
length = ~~(Math.random() * charsLen);
for (var i = 0; i < length; i++)
str += chars[~~(Math.random() * charsLen)];
return str;
;
【讨论】:
【参考方案15】:这个函数应该给出一个任意长度的随机字符串。
function randString(length)
var l = length > 25 ? 25 : length;
var str = Math.random().toString(36).substr(2, l);
if(str.length >= length)
return str;
return str.concat(this.randString(length - str.length));
我已经通过以下成功的测试对其进行了测试。
function test()
for(var x = 0; x < 300000; x++)
if(randString(x).length != x)
throw new Error('invalid result for len ' + x);
我选择 25 的原因是因为实际上从 Math.random().toString(36).substr(2, 25)
返回的字符串的长度为 25。这个数字可以随意更改。
此函数是递归的,因此调用具有非常大值的函数可能会导致Maximum call stack size exceeded
。根据我的测试,我能够获得长度为 300,000 个字符的字符串。
通过将字符串作为第二个参数发送给函数,可以将此函数转换为尾递归。我不确定JS是否使用Tail call优化
【讨论】:
【参考方案16】:好看又简单,而且不限于一定数量的字符:
let len = 20, str = "";
while(str.length < len) str += Math.random().toString(36).substr(2);
str = str.substr(0, len);
【讨论】:
【参考方案17】:你可以使用 lodash uniqueId:
_.uniqueId([prefix=''])
生成一个唯一的 ID。如果给定前缀,则将 ID 附加到它。
【讨论】:
【参考方案18】:这是一个生成随机字符串字母表的简单代码。
看看这段代码是如何工作的。go(lenthOfStringToPrint);
- 使用这个函数来生成最终的字符串。
var letters =
1: ["q","w","e","r","t","y","u","i","o","p","a","s","d","f","g","h","j","k","l","z","x","c","v","b","n","m"],
2: ["Q","W","E","R","T","Y","U","I","O","P","A","S","D","F","G","H","J","K","L","Z","X","C","V","B","N","M"]
,i,letter,final="";
random = (max,min) =>
return Math.floor(Math.random()*(max-min+1)+min);
function go(length)
final="",letter="";
for (i=1; i<=length; i++)
letter = letters[random(0,3)][random(0,25)];
final+=letter;
return final;
【讨论】:
【参考方案19】:使用 md5 库:https://github.com/blueimp/JavaScript-MD5
最短路径:
md5(Math.random())
如果要将大小限制为 5:
md5(Math.random()).substr(0, 5)
【讨论】:
以上是关于JavaScript中的随机字母数字字符串?的主要内容,如果未能解决你的问题,请参考以下文章