在JavaScript中生成随机string/字符
我想要一个由string[a-zA-Z0-9]
随机选取的5个字符的string。
用JavaScript做这个最好的方法是什么?
我认为这会对你有用:
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; } console.log(makeid());
Math.random().toString(36).substring(7);
Math.random对这种事情不好
选项1
如果你能够做这个服务器端,只需使用encryption模块
var crypto = require("crypto"); var id = crypto.randomBytes(20).toString('hex'); // "bb5dc8842ca31d4603d6aa11448d1654"
结果string将是您生成的随机字节的两倍。 每个字节编码为hex是2个字符。 20个字节将是hex的40个字符。
选项2
如果你必须做这个客户端 ,也许尝试uuid模块
var uuid = require("uuid"); var id = uuid.v4(); // "110ec58a-a0f2-4ac4-8393-c866d813b8d1"
选项3
如果你必须做这个客户端 ,你不必支持旧的浏览器,你可以没有依赖关系
// dec2hex :: Integer -> String function dec2hex (dec) { return ('0' + dec.toString(16)).substr(-2) } // generateId :: Integer -> String function generateId (len) { var arr = new Uint8Array((len || 40) / 2) window.crypto.getRandomValues(arr) return Array.from(arr, dec2hex).join('') } console.log(generateId()) // "82defcf324571e70b0521d79cce2bf3fffccd69" console.log(generateId(20)) // "c1a050a4cd1556948d41"
这是对doubletap优秀答案的一个改进。 原来有两个缺点,这里解决:
首先,正如其他人所提到的那样,产生短string甚至空string(如果随机数为0)的概率很小,这可能会破坏您的应用程序。 这是一个解决scheme:
(Math.random().toString(36)+'00000000000000000').slice(2, N+2)
其次,原来的和上面的解决scheme都将string大小N限制为16个字符。 下面将返回任意N的大小为N的string(但是请注意,使用N> 16不会增加随机性或减less冲突概率):
Array(N+1).join((Math.random().toString(36)+'00000000000000000').slice(2, 18)).slice(0, N)
说明:
- 在[0,1)范围内选取一个随机数,即在0(包括)和1(不包括)之间。
- 将数字转换为基数为36的string,即使用字符0-9和az。
- 用零填充(解决第一个问题)。
- 切掉领先的“0”。 前缀和额外的填充零。
- 重复该string足够多的时间,使其中至less有N个字符(通过使用较短的随机string作为分隔符join空string)。
- 从string中切下N个字符。
更多的想法:
- 这个解决scheme不使用大写字母,但几乎在所有情况下(没有双关语意思),这并不重要。
- 在Chrome中测量原始答案中N = 16时的最大string长度。 在Firefox中,它是N = 11。但正如所解释的,第二个解决scheme是支持任何请求的string长度,而不是添加随机性,所以它没有什么区别。
- 所有返回的string返回的概率相等,至less就Math.random()返回的结果是均匀分布的(在任何情况下,这不是密码强度随机性)。
- 不是所有可能的大小为N的string都可以被返回。 在第二种解决scheme中,这是显而易见的(因为较小的string被简单地复制),但是在原来的答案中也是如此,因为在转换为基数-36时,最后的几个比特可能不是原始随机比特的一部分。 具体来说,如果你看看Math.random()。toString(36)的结果,你会注意到最后一个字符不是均匀分布的。 同样,在几乎所有情况下,这并不重要,但我们从最开始的string开始,而不是随机string的结尾,以便短string(例如N = 1)不受影响。
更新:
下面是我想到的其他function性风格的单行代码。 他们不同于上面的解决scheme:
- 他们使用明确的任意字母表(更通用,适用于要求大写和小写字母的原始问题)。
- 所有长度为N的string返回的概率相等(即string不包含重复)。
- 它们基于map函数,而不是toString(36)技巧,这使得它们更直接,更容易理解。
所以,说你select的字母是
var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
那么这两个是相等的,所以你可以select哪一个更直观的给你:
Array(N).join().split(',').map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');
和
Array.apply(null, Array(N)).map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');
编辑:
我似乎是qubyte , Martijn de Milliano提出了类似于后者的解决scheme(kudos!),我不知怎的错过了。 既然他们看起来不是一目了然,那么我就把它留在这里,以防有人真的想要一个单一的行列:-)
另外,在所有解决scheme中用“数组”replace“新数组”,以删除更多的字节。
简单和容易+返回5个随机字符,而不是一些在这里find的最高评分答案。
Math.random().toString(36).substr(2, 5);
像这样的东西应该工作
function randomString(len, charSet) { charSet = charSet || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; var randomString = ''; for (var i = 0; i < len; i++) { var randomPoz = Math.floor(Math.random() * charSet.length); randomString += charSet.substring(randomPoz,randomPoz+1); } return randomString; }
使用默认字符集[a-zA-Z0-9]进行调用或者自行发送:
var randomValue = randomString(5); var randomValue = randomString(5, 'PICKCHARSFROMTHISSET');
function randomstring(L) { var s = ''; var randomchar = function() { var n = Math.floor(Math.random() * 62); if (n < 10) return n; //1-10 if (n < 36) return String.fromCharCode(n + 55); //AZ return String.fromCharCode(n + 61); //az } while (s.length < L) s += randomchar(); return s; } console.log(randomstring(5));
随机string生成器(字母数字|字母|数字)
/** * RANDOM STRING GENERATOR * * Info: http://stackoverflow.com/a/27872144/383904 * Use: randomString(length [,"A"] [,"N"] ); * Default: return a random alpha-numeric string * Arguments: If you use the optional "A", "N" flags: * "A" (Alpha flag) return random aZ string * "N" (Numeric flag) return random 0-9 string */ function randomString(len, an){ an = an&&an.toLowerCase(); var str="", i=0, min=an=="a"?10:0, max=an=="n"?10:62; for(;i++<len;){ var r = Math.random()*(max-min)+min <<0; str += String.fromCharCode(r+=r>9?r<36?55:61:48); } return str; }
randomString(10); // "4Z8iNQag9v" randomString(10, "A"); // "aUkZuHNcWw" randomString(10, "N"); // "9055739230"
玩的开心。 jsBin演示
虽然上面使用了对所需(A / N,A,N)输出的附加检查,但让我们将其分解到基本要素(仅用于字母数字)以便更好地理解:
- 创build一个接受参数的函数(期望的随机string结果的长度)
- 创build一个空的string像
var str = "";
连接随机字符 - 在循环内创build一个从0到61的 索引号 (0..9 + A..Z + a..z = 62)
- 创build一个有条件的逻辑来调整/修改
rand
(因为它是0..61),将它递增一些数字(参见下面的例子),以获取正确的CharCode
编号和相关的字符。 - 在循环内部连接成一个
String.fromCharCode( incremented rand )
让我们来看看angular色表格及其范围 :
_____0....9______A..........Z______a..........z___________ Character | 10 | | 26 | | 26 | Tot = 62 characters 48....57 65..........90 97..........122 CharCode ranges
Math.floor( Math.random * 62 )
的范围是从0..61
到0..61
(我们需要)。 如何解决(增加)随机获得正确的charCode范围 ?
| rand | charCode | (0..61)rand += fix = charCode ranges | ------+----------+----------+--------------------------------+-----------------+ 0..9 | 0..9 | 48..57 | rand += 48 = 48..57 | A..Z | 10..35 | 65..90 | rand += 55 /* 90-35 = 55 */ = 65..90 | a..z | 36..61 | 97..122 | rand += 61 /* 122-61 = 61 */ = 97..122 |
上表中的条件操作逻辑 :
rand += rand>9 ? ( rand<36 ? 55 : 61 ) : 48 ; // rand += true ? ( true ? 55 else 61 ) else 48 ;
如果你按照上面的说明,你应该可以创build这个字母数字片段 :
jsBin演示
function randomString( len ) { var str = ""; // String result for(var i=0; i<len; i++){ // Loop `len` times var rand = Math.floor( Math.random() * 62 ); // random: 0..61 var charCode = rand+= rand>9? (rand<36?55:61) : 48; // Get correct charCode str += String.fromCharCode( charCode ); // add Character to str } return str; // After all loops are done, return the concatenated string } console.log( randomString(10) ); // "7GL9F0ne6t"
或者如果您会:
function randomString( n ) { var r=""; while(n--)r+=String.fromCharCode((r=Math.random()*62|0,r+=r>9?(r<36?55:61):48)); return r; }
最紧凑的解决scheme,因为slice
比substring
短。 从string的末尾减去可以避免由random
函数生成的浮点符号:
Math.random().toString(36).slice(-5);
甚至
(+new Date).toString(36).slice(-5);
最简单的方法是:
(new Date%9e6).toString(36)
这会根据当前时间生成5个字符的随机string。 示例输出是4mtxj
或4mv90
或4mwp1
这个问题是,如果你在同一秒内调用它两次,它会生成相同的string。
更安全的方法是:
(0|Math.random()*9e6).toString(36)
这会产生一个4或5个字符的随机string,总是不同的。 示例输出如30jzm
或1r591
或4su1a
在这两种方式中,第一部分生成一个随机数。 .toString(36)
部分将数字转换为一个base36(alphadecimal)表示。
这里有一些简单的内衬。 更改new Array(5)
来设置长度。
包括0-9a-z
new Array(5).join().replace(/(.|$)/g, function(){return ((Math.random()*36)|0).toString(36);})
包括0-9a-zA-Z
new Array(5).join().replace(/(.|$)/g, function(){return ((Math.random()*36)|0).toString(36)[Math.random()<.5?"toString":"toUpperCase"]();});
如果你使用Lodash或Underscore ,那么它很简单:
var randomVal = _.sample('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 5).join('');
我知道每个人都已经知道了,但是我觉得要以最轻量级的方式去做这件事(代码轻,而不是CPU):
function rand(length, current) { current = current ? current : ''; return length ? rand(--length, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz".charAt(Math.floor(Math.random() * 60)) + current) : current; } console.log(rand(5));
这是我创build的方法。
它将创build一个包含大写和小写字符的string。
此外,我还包括将创build一个字母数字string的function。
工作示例:
http://jsfiddle.net/greatbigmassive/vhsxs/ (仅限alpha)
http://jsfiddle.net/greatbigmassive/PJwg8/ (字母数字)
function randString(x){ var s = ""; while(s.length<x&&x>0){ var r = Math.random(); s+= String.fromCharCode(Math.floor(r*26) + (r>0.5?97:65)); } return s; }
2015年7月升级
这是做同样的事情,但更有意义,包括所有字母。
var s = ""; while(s.length<x&&x>0){ v = Math.random()<0.5?32:0; s += String.fromCharCode(Math.round(Math.random()*((122-v)-(97-v))+(97-v))); }
如果任何人对单线程(虽然没有为了方便起见而被格式化)感兴趣,那就是一次分配内存(但是注意对于小string来说真的没有关系),这里是如何做到的:
Array.apply(0, Array(5)).map(function() { return (function(charset){ return charset.charAt(Math.floor(Math.random() * charset.length)) }('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')); }).join('')
你可以用你想要的string的长度replace5
。 感谢@AriyaHidayat在这篇文章中解决map
函数不能处理由Array(5)
创build的稀疏数组。
假设你使用下划线 ,可以用两行来优雅地生成随机string:
var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; var random = _.sample(possible, 5).join('');
你可以遍历一系列的项目,recursion地将它们添加到一个stringvariables,例如,如果你想要一个随机的DNA序列:
function randomDNA(len) { len = len || 100 var nuc = new Array("A", "T", "C", "G") var i = 0 var n = 0 s = '' while (i <= len - 1) { n = Math.floor(Math.random() * 4) s += nuc[n] i++ } return s } console.log(randomDNA(5));
function randomString (strLength, charSet) { var result = []; strLength = strLength || 5; charSet = charSet || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; while (--strLength) { result.push(charSet.charAt(Math.floor(Math.random() * charSet.length))); } return result.join(''); }
这是干净的,因为它会得到。 它也很快, http://jsperf.com/ay-random-string 。
这是肯定的
<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>
生成10个字符的长string。 长度由参数设置(默认为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; }
这是#1答案的testing脚本(谢谢@ csharptest.net)
该脚本运行makeid()
1 million
次,正如你可以看到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');
这个小巧的小技巧呢?
var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; var stringLength = 5; function pickRandom() { return possible[Math.floor(Math.random() * possible.length)]; } var randomString = Array.apply(null, Array(stringLength)).map(pickRandom).join('');
你需要在那里的Array.apply
欺骗空数组是一个未定义的数组。
如果您正在为ES2015编码,那么构buildarrays会更简单一些:
var randomString = Array.from({ length: stringLength }, pickRandom).join('');
快速和改进的algorithm。 不保证统一(见评论)。
function getRandomId(length) { if (!length) { return ''; } const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; let result = ''; let array; if ('Uint8Array' in self && 'crypto' in self && length <= 65536) { array = new Uint8Array(length); self.crypto.getRandomValues(array); } else { array = new Array(length); for (let i = 0; i < length; i++) { array[i] = Math.floor(Math.random() * 62); } } for (let i = 0; i < length; i++) { result += possible.charAt(array[i] % 62); } return result; }
通过回答Gertas和Dragon提出的问题来拓展Doubletap的优雅范例。 只需添加一个while循环来testing这些罕见的空情况,并将字符数限制为5。
function rndStr() { x=Math.random().toString(36).substring(7).substr(0,5); while (x.length!=5){ x=Math.random().toString(36).substring(7).substr(0,5); } return x; }
这里是一个jsfiddle警告你的结果: http : //jsfiddle.net/pLJJ7/
"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('');};
会生成一个随机字母数字string,其长度为第一个/调用string
这是我用的。 这里有一对夫妇的组合。 我在循环中使用它,它生成的每个ID都是唯一的。 它可能不是5个字符,但保证是唯一的。
var newId = "randomid_" + (Math.random() / +new Date()).toString(36).replace(/[^az]+/g, '');
如果图书馆是可能的,Chance.js可能会有帮助: http ://chancejs.com/#string
我喜欢doubletap的Math.random()。toString(36).substring(7)答案的简单,但并不是说它有如hacklikecrack正确指出的那么多的碰撞。 它产生了11个string,但是样本量为100万,重复率为11%。
这是一个较长的(但仍然很短)和较慢的select,在一百万的样本空间中只有133个重复。 在极less数情况下,string仍然会短于11个字符:
Math.abs(Math.random().toString().split('') .reduce(function(p,c){return (p<<5)-p+c})).toString(36).substr(0,11);
function性的方法。 只有在您的应用程序的其他部分可以利用function先决条件时,此答案才是实用的。 performance可能是垃圾,但写作却非常有趣。
// functional prerequisites const U = f=> f (f) const Y = U (h=> f=> f (x=> h (h) (f) (x))) const comp = f=> g=> x=> f (g (x)) const foldk = Y (h=> f=> y=> ([x, ...xs])=> x === undefined ? y : f (y) (x) (y=> h (f) (y) (xs))) const fold = f=> foldk (y=> x=> k=> k (f (y) (x))) const map = f=> fold (y=> x=> [...y, f (x)]) ([]) const char = x=> String.fromCharCode(x) const concat = x=> y=> y.concat(x) const concatMap = f=> comp (fold (concat) ([])) (map (f)) const irand = x=> Math.floor(Math.random() * x) const sample = xs=> xs [irand (xs.length)] // range : make a range from x to y; [x...y] // Number -> Number -> [Number] const range = Y (f=> r=> x=> y=> x > y ? r : f ([...r, x]) (x+1) (y) ) ([]) // srand : make random string from list or ascii code ranges // [(Range a)] -> Number -> [a] const srand = comp (Y (f=> z=> rs=> x=> x === 0 ? z : f (z + sample (rs)) (rs) (x-1) ) ([])) (concatMap (map (char))) // idGenerator : make an identifier of specified length // Number -> String const idGenerator = srand ([ range (48) (57), // include 0-9 range (65) (90), // include AZ range (97) (122) // include az ]) console.log (idGenerator (6)) //=> TT688X console.log (idGenerator (10)) //=> SzaaUBlpI1 console.log (idGenerator (20)) //=> eYAaWhsfvLDhIBID1xRh
你可以使用coderain 。 这是一个根据给定模式生成随机码的库。 使用#
作为大写和小写字符以及数字的占位符:
var cr = new CodeRain("#####"); console.log(cr.next());
还有其他的占位符,如大写字母A
或数字9
。
What may be useful is that calling .next()
will always give you a unique result so you don't have to worry about duplicates.
Here is a demo application that generates a list of unique random codes .
Full disclosure: I'm the author of coderain.