Generate random string/characters in JavaScript
我想要一个由从集合
使用JavaScript最好的方法是什么?
1 2 | let r = Math.random().toString(36).substring(7); console.log("random", r); |
注:上述算法存在以下缺点:
- 它将生成0到6个字符之间的任何地方,因为当串接浮点时,尾随零被删除。
- 它深深地依赖于用来串接浮点数的算法,这是非常复杂的。(见"如何准确打印浮点数"一文。)
Math.random() 可能产生可预测的(随机查找的)输出,但不是真正随机的),这取决于实现。当需要保证唯一性或不可预测性时,结果字符串不适用。- 即使它生成了6个均匀随机、不可预测的字符,由于生日悖论,您也可以在只生成大约50000个字符串后看到一个副本。(平方英尺(36^6)=46656)
我想这对你有用:
1 2 3 4 5 6 7 8 9 10 11 | function makeid(length) { var text =""; var possible ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; for (var i = 0; i < length; i++) text += possible.charAt(Math.floor(Math.random() * possible.length)); return text; } console.log(makeid(5)); |
随机数对这种事情不好。
选项1
如果您能够在服务器端执行此操作,只需使用加密模块-
1 2 3 4 | var crypto = require("crypto"); var id = crypto.randomBytes(20).toString('hex'); //"bb5dc8842ca31d4603d6aa11448d1654" |
得到的字符串将是您生成的随机字节的两倍;每个编码为十六进制的字节是2个字符。20字节将是40个十六进制字符。
选项2
如果必须这样做,请尝试UUID模块-
1 2 3 4 | var uuid = require("uuid"); var id = uuid.v4(); //"110ec58a-a0f2-4ac4-8393-c866d813b8d1" |
选项3
如果必须这样做,并且不必支持旧的浏览器,则可以不依赖于其他浏览器来完成此操作。-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // dec2hex :: Integer -> String // i.e. 0-255 -> '00'-'ff' 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" |
有关
The
crypto.getRandomValues() method lets you get cryptographically strong random values. The array given as the parameter is filled with random numbers (random in its cryptographic meaning).
下面是一个小控制台示例-
1 2 3 4 5 6 7 8 9 10 11 12 | > var arr = new Uint8Array(4) # make array of 4 bytes (values 0-255) > arr Uint8Array(4) [ 0, 0, 0, 0 ] > window.crypto Crypto { subtle: SubtleCrypto } > window.crypto.getRandomValues() TypeError: Crypto.getRandomValues requires at least 1 argument, but only 0 were passed > window.crypto.getRandomValues(arr) Uint8Array(4) [ 235, 229, 94, 228 ] |
对于IE11支持,您可以使用-
1 | (window.crypto || window.msCrypto).getRandomValues(arr) |
有关浏览器覆盖范围,请参阅https://caniuse.com/feat=getrandomvalues
短、易、可靠
只返回5个随机字符,而不是这里找到的一些最受欢迎的答案。
1 | Math.random().toString(36).substr(2, 5); |
这是对Doubletap优秀答案的改进。原件有两个缺点,在这里解决:
首先,正如其他人提到的,它产生短字符串甚至空字符串的概率很小(如果随机数为0),这可能会破坏应用程序。以下是一个解决方案:
1 | (Math.random().toString(36)+'00000000000000000').slice(2, N+2) |
其次,上面的原始和解决方案都将字符串大小n限制为16个字符。对于任何n,下面将返回一个大小为n的字符串(但请注意,使用n>16不会增加随机性或降低碰撞概率):
1 | Array(N+1).join((Math.random().toString(36)+'00000000000000000').slice(2, 18)).slice(0, N) |
说明:
进一步思考:
- 此解决方案不使用大写字母,但在几乎所有情况下(不打算使用双关语),这并不重要。
- 原始答案中n=16处的最大字符串长度用铬测量。在火狐中,它是n=11。但是正如所解释的,第二个解决方案是支持任何请求的字符串长度,而不是增加随机性,所以它没有什么区别。
- 所有返回的字符串都有相同的返回概率,至少在math.random()返回的结果均匀分布的情况下(在任何情况下,这都不是加密强度的随机性)。
- 并非所有可能的大小为n的字符串都可以返回。在第二种解决方案中,这是显而易见的(因为较小的字符串只是简单地被复制),但在原始答案中,这是正确的,因为在转换为base-36时,最后几个位可能不是原始随机位的一部分。具体来说,如果查看math.random().toString(36)的结果,您会发现最后一个字符的分布不均匀。同样,在几乎所有的情况下,它都不重要,但是我们从随机字符串的开始而不是结束分割最后一个字符串,这样短字符串(例如n=1)就不会受到影响。
更新:
这是我想出的另外两个功能风格的一句话。它们与上述解决方案的不同之处在于:
- 他们使用一个明确的任意字母表(更通用,并且适用于要求大写和小写字母的原始问题)。
- 所有长度为n的字符串都有相同的返回概率(即字符串不包含重复)。
- 它们基于一个映射函数,而不是ToString(36)技巧,这使得它们更加简单易懂。
所以说你选择的字母表是
1 | var s ="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; |
然后这两个值是相等的,因此您可以选择对您更直观的值:
1 | Array(N).join().split(',').map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join(''); |
和
1 | Array.apply(null, Array(N)).map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join(''); |
编辑:
我似乎是库比特和马蒂金·德米利亚诺想出了类似于后者的解决方案(荣誉!)我不知怎么地错过了。既然它们看起来不那么短,我还是把它放在这儿,以防有人真的想要一条单线纸。
此外,在所有解决方案中,将"new array"替换为"array",以减少更多的字节。
像这样的东西应该管用
1 2 3 4 5 6 7 8 9 | 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]调用或自己发送:
1 2 3 | var randomValue = randomString(5); var randomValue = randomString(5, 'PICKCHARSFROMTHISSET'); |
1 2 3 4 5 6 7 8 9 10 11 12 | 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); //A-Z return String.fromCharCode(n + 61); //a-z } while (s.length < L) s += randomchar(); return s; } console.log(randomstring(5)); |
最紧凑的解决方案,因为
1 | Math.random().toString(36).slice(-5); |
甚至
1 | (+new Date).toString(36).slice(-5); |
1 2 3 4 5 | // Using Math.random console.log(Math.random().toString(36).slice(-5)); // Using new Date console.log((+new Date).toString(36).slice(-5)); |
随机字符串生成器(字母数字字母数字)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /** * 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 a-Z 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; } |
1 2 3 | randomString(10); //"4Z8iNQag9v" randomString(10,"A"); //"aUkZuHNcWw" randomString(10,"N"); //"9055739230" |
玩得高兴。JSBN演示
虽然上面对所需(A/N、A、N)输出使用了附加检查,让我们将其分解为基本要素(仅限字母数字),以便更好地理解:
- 创建接受参数的函数(随机字符串结果的所需长度)
- 创建一个像
var str =""; 这样的空字符串来连接随机字符 - 在循环内创建从0到61(0..9+a..z+a..z=62)的
rand 索引号。 - 创建一个条件逻辑来调整/修复
rand (因为它是0..61),将它增加一些数字(见下面的例子),以返回正确的CharCode 数字和相关字符。 - 在连接到
str aString.fromCharCode( incremented rand ) 的循环内部
让我们想象一下字符表及其范围:
1 2 3 | _____0....9______A..........Z______a..........z___________ Character | 10 | | 26 | | 26 | Tot = 62 characters 48....57 65..........90 97..........122 CharCode ranges |
1 2 3 4 5 | | 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 | |
上表中的条件运算逻辑:
1 2 | rand += rand>9 ? ( rand<36 ? 55 : 61 ) : 48 ; // rand += true ? ( true ? 55 else 61 ) else 48 ; |
如果按照上述说明进行操作,您应该能够创建这个字母数字片段:
JSBN演示
1 2 3 4 5 6 7 8 9 10 11 | 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" |
或者如果你愿意:
1 2 3 4 5 | 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; } |
带有ES6 Spread Operator的更新版本:
30 是任意数字,您可以选择任何您想要的令牌长度。36 是可以传递给numeric.toString()的最大基数,表示所有数字和a-z小写字母。- 用
2 从随机串中选取2th号,如:"0.mfbiohx64i" ,可以取0. 后的任何索引。
最简单的方法是:
1 | (new Date%9e6).toString(36) |
这将根据当前时间生成5个字符的随机字符串。示例输出为
问题在于,如果在同一秒内调用它两次,它将生成相同的字符串。
更安全的方法是:
1 | (0|Math.random()*9e6).toString(36) |
这将生成一个4或5个字符的随机字符串,始终是不同的。示例输出类似于
第一部分以两种方式生成随机数。
这里有一些简单的一句话。更改
1 | new Array(5).join().replace(/(.|$)/g, function(){return ((Math.random()*36)|0).toString(36);}) |
包括
1 | new Array(5).join().replace(/(.|$)/g, function(){return ((Math.random()*36)|0).toString(36)[Math.random()<.5?"toString":"toUpperCase"]();}); |
我知道每个人都已经把它做好了,但我想以最轻量级的方式(轻量级代码,而不是CPU)尝试一下:
1 2 3 4 5 6 | function rand(length, current) { current = current ? current : ''; return length ? rand(--length,"0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz".charAt(Math.floor(Math.random() * 60)) + current) : current; } console.log(rand(5)); |
这需要一点时间,但我认为它确实显示了JavaScript的语法是多么的棒。
如果您使用的是lodash或下划线,那么它非常简单:
1 | var randomVal = _.sample('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 5).join(''); |
这是我创建的方法。
它将创建一个包含大小写字符的字符串。
此外,我还包含了将创建字母数字字符串的函数。
工作示例:
http://jsfiddle.net/greatbigmassy/vhsxs/(仅限阿尔法)
http://jsfiddle.net/greatbigmassive/pjwg8/(字母数字)
1 2 3 4 5 6 7 8 | 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月
这做了同样的事情,但更有意义,包括所有的字母。
1 2 3 4 5 | 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))); } |
假设您使用下划线,就可以在两行中优雅地生成随机字符串:
1 2 | var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; var random = _.sample(possible, 5).join(''); |
为满足要求[A-ZA-Z0-9]和长度=5,使用
1 | btoa(Math.random()).substr(5, 5); |
将出现小写字母、大写字母和数字。
如果任何人对一个一次性分配内存的单行程序感兴趣(尽管不是为了方便而格式化为这样),请注意,对于小字符串来说,这并不重要),下面是如何做到这一点的方法:
1 2 3 4 5 | Array.apply(0, Array(5)).map(function() { return (function(charset){ return charset.charAt(Math.floor(Math.random() * charset.length)) }('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')); }).join('') |
您可以将
快速改进的算法。不保证统一(见注释)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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; } |
您可以循环遍历一个项目数组并递归地将它们添加到字符串变量中,例如,如果您想要一个随机的DNA序列:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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)); |
我没有找到同时支持小写和大写字符的干净解决方案。
仅支持小写:
基于该解决方案支持小写和大写:
更改
1 2 3 4 5 6 7 8 9 10 11 12 | 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://jspef.com/ay-random-string。
这当然行
1 2 3 4 5 6 7 8 9 10 11 | <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; } |
您可以使用coderain。它是一个根据给定模式生成随机代码的库。使用
1 2 | var cr = new CodeRain("#####"); console.log(cr.next()); |
还有其他占位符,如大写字母的
可能有用的是,调用
这里是一个演示应用程序,它生成一个唯一的随机代码列表。
完全公开:我是《法典》的作者。
回答"我需要随机字符串"问题(无论用什么语言)的问题实际上是每个解决方案都使用了有缺陷的字符串长度的主要规范。这些问题本身很少揭示为什么需要随机字符串,但我要挑战的是,你很少需要长度为8的随机字符串。您永远需要的是一些唯一的字符串,例如,为了某种目的用作标识符。
有两种获得严格唯一字符串的主要方法:确定性(非随机)和存储/比较(繁重)。我们该怎么办?我们放弃鬼魂。我们改为使用概率唯一性。也就是说,我们接受存在一些(无论多小)风险,我们的字符串不会是唯一的。这是理解碰撞概率和熵有帮助的地方。
因此,我将把不变的需求重新表述为需要一些具有小重复风险的字符串。作为一个具体的例子,假设您希望生成一个潜在的500万个ID。您不希望存储和比较每个新字符串,并且希望它们是随机的,所以您接受了一些重复的风险。例如,假设重复的概率小于1万亿分之一。所以你需要多长的绳子?好吧,这个问题没有具体说明,因为它取决于使用的字符。但更重要的是,它被误导了。您需要的是字符串熵的规范,而不是它们的长度。熵可以直接与某些字符串的重复概率有关。字符串长度不能。
这就是像entropyString这样的库可以提供帮助的地方。使用
1 2 3 4 5 6 | import {Random, Entropy} from 'entropy-string' const random = new Random() const bits = Entropy.bits(5e6, 1e12) const string = random.string(bits) |
"44hTNghjNHGGRHqH9"
1 2 3 4 5 6 | import {Random, Entropy, charSet16} from './entropy-string' const random = new Random(charSet16) const bits = Entropy.bits(5e6, 1e12) const string = random.string(bits) |
"27b33372ade513715481f"
请注意,由于所用字符集中的字符总数不同,字符串长度也不同。在指定数量的潜在字符串中重复的风险相同。字符串长度不是。最重要的是,重复的风险和潜在的字符串数量是明确的。不用再猜测绳子的长度了。
像这样的东西怎么样:
生成10个字符长的字符串。长度由参数设置(默认为10)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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 2 3 4 5 6 7 8 | function randStr(len) { let s = ''; while (s.length < len) s += Math.random().toString(36).substr(2, len - s.length); return s; } // usage console.log(randStr(50)); |
这个函数的好处是,您可以得到不同长度的随机字符串,并确保字符串的长度。
区分大小写所有字符:1 2 3 4 5 6 7 8 | function randStr(len) { let s = ''; while (len--) s += String.fromCodePoint(Math.floor(Math.random() * (126 - 33) + 33)); return s; } // usage console.log(randStr(50)); |
1 2 3 4 5 6 7 8 9 10 | function randStr(len, chars='abc123') { let s = ''; while (len--) s += chars[Math.floor(Math.random() * chars.length)]; return s; } // usage console.log(randStr(50)); console.log(randStr(50, 'abc')); console.log(randStr(50, 'aab')); // more a than b |
这是1个答案的测试脚本(谢谢@csharptest.net)
脚本运行
注意:节点堆栈大小限制超过了400万左右,所以您不能运行这500万次,它永远不会完成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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'); |
这个小把戏怎么样?
1 2 3 4 5 6 7 8 | 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(''); |
你需要有
如果您要为ES2015编码,那么构建阵列就要简单一点:
1 | var randomString = Array.from({ length: stringLength }, pickRandom).join(''); |
通过回答Gertas和Dragon提出的问题,扩展Doubletap的优雅典范。只需添加一个while循环来测试这些罕见的空情况,并将字符限制为5个。
1 2 3 4 5 6 7 | 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; } |
下面是一个jsiddle,它向您发出一个结果警告:http://jsfiddle.net/pljj7/
这是我用过的。一对组合在一起。我在一个循环中使用它,它产生的每个ID都是唯一的。它可能不是5个字符,但肯定是独一无二的。
1 2 3 | var newId = "randomid_" + (Math.random() / +new Date()).toString(36).replace(/[^a-z]+/g, ''); |
如果库是可能的,chance.js可能会有帮助:http://chance js.com/string
这个结合了许多答案。
1 2 3 | var randNo = Math.floor(Math.random() * 100) + 2 +"" + new Date().getTime() + Math.floor(Math.random() * 100) + 2 + (Math.random().toString(36).replace(/[^a-zA-Z]+/g, '').substr(0, 5)); console.log(randNo); |
我用了一个月,效果很好。
下面这个怎么样…这将产生真正的随机值:
1 2 3 4 5 6 7 8 | function getRandomStrings(length) { const value = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; const randoms = []; for(let i=0; i < length; i++) { randoms.push(value[Math.floor(Math.random()*value.length)]); } return randoms.join(''); } |
但是如果您在ES6中寻找一个较短的语法:
1 | const getRandomStrings = length => Math.random().toString(36).substr(-length); |
同样基于DoubleTap的答案,这个函数处理任意长度的随机必需字符(仅下方),并不断生成随机数,直到收集到足够的字符为止。
1 2 3 4 5 6 7 8 9 10 | function randomChars(len) { var chars = ''; while (chars.length < len) { chars += Math.random().toString(36).substring(2); } // Remove unnecessary additional characters. return chars.substring(0, len); } |
1 2 3 4 5 | "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('');}; |
将生成具有第一个/调用字符串长度的随机字母数字字符串
1 | ",,,,,".replace(/,/g,function (){return"AzByC0xDwEv9FuGt8HsIrJ7qKpLo6MnNmO5lPkQj4RiShT3gUfVe2WdXcY1bZa".charAt(Math.floor(Math.random()*62))}); |
对于具有大小写字母和数字(0-9a-z a-z)的字符串,这可能是最适合缩小的版本:
1 2 3 4 5 6 7 8 9 10 11 | function makeId(length) { var id = ''; var rdm62; while (length--) { // Generate random integer between 0 and 61, 0|x works for Math.floor(x) in this case rdm62 = 0 | Math.random() * 62; // Map to ascii codes: 0-9 to 48-57 (0-9), 10-35 to 65-90 (A-Z), 36-61 to 97-122 (a-z) id += String.fromCharCode(rdm62 + (rdm62 < 10 ? 48 : rdm62 < 36 ? 55 : 61)) } return id; } |
这个函数的内容缩小到97个字节,而最上面的答案需要149个字节(因为字符列表)。
这是Doubletap答案的一个稍微改进的版本。当
1 | ((Math.random()+3*Number.MIN_VALUE)/Math.PI).toString(36).slice(-5) |
教人钓鱼:
程序员用激光切割纸张,而不是用链锯。使用边缘,语言特定的方法来产生最小的,最模糊的代码是可爱的和所有,但永远不会提供一个完整的解决方案。你必须使用合适的工具来完成这项工作。
您需要的是一个字符串,字符由字节表示。而且,我们可以用数字在JavaScript中表示一个字节。那么,我们应该生成一个这些数字的列表,并将它们转换为字符串。你不需要日期,或者base64;math.random()会给你一个数字,string.fromcharcode()会把它变成一个字符串。容易的。
但是,哪个数字等于哪个字符?UTF-8是Web上用来将字节解释为字符的主要标准(尽管JavaScript在内部使用UTF-16,但它们是重叠的)。程序员解决这个问题的方法是查看文档。
UTF-8以0到128之间的数字列出键盘上的所有键。有些是非印刷品。只需在随机字符串中挑选您想要的字符,然后使用随机生成的数字搜索它们。
Bellow是一个函数,它的长度实际上是无限的,在一个循环中生成一个随机数,并搜索下面128个UTF-8代码中的所有打印字符。熵是固有的,因为并非所有随机数都会每次命中(非打印字符、空白等)。当您添加更多的字符时,它的执行速度也会更快。
我已经包含了线程中讨论的大多数优化:
- 双层瓷砖比数学地板快。
- "if"语句比正则表达式快
- 推到数组比字符串串联更快
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | function randomID(len) { var char; var arr = []; var len = len || 5; do { char = ~~(Math.random() * 128); if (( (char > 47 && char < 58) || // 0-9 (char > 64 && char < 91) || // A-Z (char > 96 && char < 123) // a-z // || (char > 32 && char < 48) // !"#$%&,()*+'-./ // || (char > 59 && char < 65) // <=>?@ // || (char > 90 && char < 97) // [\]^_` // || (char > 123 && char < 127) // {|}~ ) //security conscious removals:" ' \ ` //&& (char != 34 && char != 39 && char != 92 && char != 96) ) { arr.push(String.fromCharCode(char)) } } while (arr.length < len); return arr.join('') } var input = document.getElementById('length'); input.onfocus = function() { input.value = ''; } document.getElementById('button').onclick = function() { var view = document.getElementById('string'); var is_number = str => ! Number.isNaN( parseInt(str)); if ( is_number(input.value)) view.innerText = randomID(input.value); else view.innerText = 'Enter a number'; } |
1 2 3 4 5 6 7 8 9 10 | #length { width: 3em; color: #484848; } #string { color: #E83838; font-family: 'sans-serif'; word-wrap: break-word; } |
1 2 3 4 | <input id="length" type="text" value='#'/> <input id="button" type="button" value="Generate" /> <p id="string"> </p> |
为什么要这样乏味?因为你可以。你是个程序员。你可以让电脑做任何事!另外,如果你想要一串希伯来文字符怎么办?这并不难。在UTF-8标准中查找这些字符并搜索它们。把自己从像ToString(36)这样的麦当劳方法中解放出来。
有时,降低抽象级别是创建真正的解决方案所需要的。了解手边的基本原理可以让您根据自己的喜好定制代码。也许您需要无限生成的字符串来填充循环缓冲区?也许你希望所有生成的字符串都是回文?为什么要克制自己?
随机Unicode字符串
此方法将返回一个随机字符串,其中包含任何受支持的Unicode字符,这不是OP要求的100%,而是我要查找的内容:
1 2 3 4 5 | function randomUnicodeString(length){ return Array.from({length: length}, ()=>{ return String.fromCharCode(Math.floor(Math.random() * (65536))) }).join('') } |
理论基础
这是谷歌在搜索"随机字符串javascript"时的首要结果,但OP只要求a-za-z0-9。
随机数值(最多16位)
1 2 3 4 5 6 7 8 9 | /** * Random numeric value (up to 16 digits) * @returns {String} */ function randomUid () { return String(Math.floor(Math.random() * 9e15)) } // randomUid() ->"3676724552601324" |
我喜欢doubletap的math.random().tostring(36).substring(7)答案的敏捷性,但并不像hacklikecrack正确指出的那样,它有如此多的碰撞。它生成了11个字符字符串,但在100万个样本中的重复率为11%。
这里有一个较长(但仍然较短)和较慢的替代方案,在100万个样本空间中只有133个副本。在极少数情况下,字符串仍将短于11个字符:
1 2 | Math.abs(Math.random().toString().split('') .reduce(function(p,c){return (p<<5)-p+c})).toString(36).substr(0,11); |
我用的是
这将在变量C中存储5个字母数字字符。
1 | for(var c = ''; c.length < 5;) c += Math.random().toString(36).substr(2, 1) |
这里有一种不同的方法,按基固定长度,不使用regexp替换lack(基于@bendytree的答案);
1 2 3 4 5 6 7 8 9 10 | function rand(base) { // default base 10 base = (base >= 2 && base <= 36) ? base : 10; for (var i = 0, ret = []; i < base; i++) { ret[i] = ((Math.random() * base) | 0).toString(base) // include 0-9a-zA-Z? // [Math.random() < .5 ? 'toString' : 'toUpperCase'](); } return ret.join(''); } |
正如这里的一些人指出的,将
随机性差。生成的字符数各不相同,平均情况下取决于浮点数字在JavaScript中如何工作的复杂细节。如果我尝试生成11个或更少的字符,但不超过11个字符,这似乎是可行的。它也不灵活。不容易允许或禁止某些字符。
我有一个紧凑的解决方案,它不存在这些问题,对于任何使用lodash的人:
1 | _.range(11).map(i => _.sample("abcdefghijklmnopqrstuvwxyz0123456789")).join('') |
如果要允许某些字符(如大写字母)或禁止某些字符(如
非常简单
1 2 3 4 5 6 7 | function getRandomColor(){ var color=''; while(color.length<6){ color=Math.floor(Math.random()*16777215).toString(16); } return '#'+color; } |
试试这个,我每次都用:
1 2 3 4 5 6 7 8 9 | function myFunction() { var hash ="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012346789"; var random8 = ''; for(var i = 0; i < 5; i++){ random8 += hash[parseInt(Math.random()*hash.length)]; } console.log(random8); document.getElementById("demo").innerHTML ="Your 5 character string ===>"+random8; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <!DOCTYPE html> <html> <body> <p> Click the button to genarate 5 character random string . </p> <button onclick="myFunction()">Click me</button> <p id="demo"> </p> </body> </html> |
在下面的代码中,我生成了8个字符的随机代码
1 2 3 4 5 6 7 8 9 10 11 | function RandomUnique(){ var charBank ="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012346789"; var random= ''; var howmanycharacters = 8; for (var i = 0; i < howmanycharacters ; i++) { random+= charBank[parseInt(Math.random() * charBank.lenght)]; } return random; } var random = RandomUnique(); console.log(random); |
npm模块anyid提供了灵活的API来生成各种类型的字符串id/代码。
1 | const id = anyid().encode('Aa0').length(5).random().id(); |
一种实用的方法。只有在应用程序的其他部分可以利用功能先决条件时,此答案才是可行的。这个表演可能是垃圾,但写起来非常有趣。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | // 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 A-Z range (97) (122) // include a-z ]) console.log (idGenerator (6)) //=> TT688X console.log (idGenerator (10)) //=> SzaaUBlpI1 console.log (idGenerator (20)) //=> eYAaWhsfvLDhIBID1xRh |
在我看来,如果不增加魔法,做太多事情的功能,就很难打破
可能会有轻微的改善
1 2 3 4 5 6 7 8 9 10 11 | // ord : convert char to ascii code // Char -> Number const ord = x => x.charCodeAt(0) // idGenerator : make an identifier of specified length // Number -> String const idGenerator = srand ([ range (ord('0')) (ord('9')), range (ord('A')) (ord('Z')), range (ord('a')) (ord('z')) ]) |
玩得开心。告诉我你喜欢什么/学习什么^^
我制作了一个字符串原型,可以生成一个给定长度的随机字符串。
如果需要特殊字符,也可以进行分解,并且可以避免使用某些字符。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /** * STRING PROTOTYPE RANDOM GENERATOR * Used to generate a random string * @param {Boolean} specialChars * @param {Number} length * @param {String} avoidChars */ String.prototype.randomGenerator = function (specialChars = false, length = 1, avoidChars = '') { let _pattern = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; _pattern += specialChars === true ? '(){}[]+-*/=' : ''; if (avoidChars && avoidChars.length) { for (let char of avoidChars) { _pattern = _pattern.replace(char, ''); } } let _random = ''; for (let element of new Array(parseInt(length))) { _random += _pattern.charAt(Math.floor(Math.random() * _pattern.length)); } return _random; }; |
您可以这样使用:
1 2 | // Generate password with specialChars which contains 10 chars and avoid iIlL chars var password = String().randomGenerator(true, 10, 'iIlL'); |
希望它有帮助。
这是用于Firefox Chrome代码(插件等)
它可以帮你节省几个小时的研究时间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | function randomBytes( amount ) { let bytes = Cc[ '@mozilla.org/security/random-generator;1' ] .getService ( Ci.nsIRandomGenerator ) .generateRandomBytes( amount, '' ) return bytes.reduce( bytes2Number ) function bytes2Number( previousValue, currentValue, index, array ) { return Math.pow( 256, index ) * currentValue + previousValue } } |
使用它作为:
1 2 3 | let strlen = 5 , radix = 36 , filename = randomBytes( strlen ).toString( radix ).splice( - strlen ) |
递归解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 | function generateRamdomId (seedStr) { const len = seedStr.length console.log('possibleStr', seedStr , ' len ', len) if(len <= 1){ return seedStr } const randomValidIndex = Math.floor(Math.random() * len) const randomChar = seedStr[randomValidIndex] const chunk1 = seedStr.slice(0, randomValidIndex) const chunk2 = seedStr.slice(randomValidIndex +1) const possibleStrWithoutRandomChar = chunk1.concat(chunk2) return randomChar + generateRamdomId(possibleStrWithoutRandomChar) |
}
你可以使用你想要的种子,如果你不想,不要重复字符。例子
1 | generateRandomId("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") |
您可以使用base64:
1 2 3 4 5 6 7 8 9 10 11 | function randomString(length) { var rtn =""; do { rtn += btoa("" + Math.floor(Math.random() * 100000)).substring(0, length); } while(rtn.length < length); return rtn; } |
另一种将字符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | function randomString(length) { if ( length <= 0 ) return""; var getChunk = function(){ var i, //index iterator rand = Math.random()*10e16, //execute random once bin = rand.toString(2).substr(2,10), //random binary sequence lcase = (rand.toString(36)+"0000000000").substr(0,10), //lower case random string ucase = lcase.toUpperCase(), //upper case random string a = [lcase,ucase], //position them in an array in index 0 and 1 str =""; //the chunk string b = rand.toString(2).substr(2,10); for ( i=0; i<10; i++ ) str += a[bin[i]][i]; //gets the next character, depends on the bit in the same position as the character - that way it will decide what case to put next return str; }, str =""; //the result string while ( str.length < length ) str += getChunk(); str = str.substr(0,length); return str; } |
将字符作为
1 2 3 4 5 | Array.apply(null, Array(5)) .map(function(){ return this[Math.floor(Math.random()*this.length)]; },"abcdefghijklmnopqrstuvwxyz") .join(''); |
下面是CoffeeDescript中的一个示例:
1 2 3 | String::add_Random_Letters = (size )-> charSet = 'abcdefghijklmnopqrstuvwxyz' @ + (charSet[Math.floor(Math.random() * charSet.length)] for i in [1..size]).join('') |
可以使用的
1 2 | value ="abc_" value_with_exta_5_random_letters = value.add_Random_Letters(5) |
这是CoffeeScript版本一行代码
1 | genRandomString = (length,set) -> [0...length].map( -> set.charAt Math.floor(Math.random() * set.length)).join('') |
用途:
1 | genRandomString 5, 'ABCDEFTGHIJKLMNOPQRSTUVWXYZ' |
输出:
1 | 'FHOOV' # random string of length 5 in possible set A~Z |