2843

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

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

5

94答案94

重置为默认值
3714

我认为这对你很有用:

函数makeid(长度){让结果=“”;const characters=“ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789”;const charactersLength=characters.length;让计数器=0;while(计数器<长度){结果+=characters.charAt(Math.floor(Math.random()*charactersLength));计数器+=1;}返回结果;}console.log(makeid(5));

21
3194

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

注:上述算法存在以下缺点:

  • 它将生成0到6个字符之间的任意字符,这是因为字符串化浮点时去掉了尾随的零。
  • 它在很大程度上依赖于用于字符串化浮点数的算法,这非常复杂。(见论文“如何准确打印浮点数字”.)
  • 数学随机数()根据实现,可能会产生可预测的(“随机”,但不是真正随机的)输出。当需要保证唯一性或不可预测性时,结果字符串不适用。
  • 即使它生成了6个统一的随机、不可预测的字符,由于生日悖论.(平方码(36^6)=46656)
23
  • 332
    Math.random().toString(36).substr(2,5),因为.子字符串(7)使其长度超过5个字符。还是满分!
    – 
    评论 2012年5月7日8:13
  • 86
    @独家报道到字符串javascript中数字类型的方法采用一个可选参数将数字转换为给定的基数。例如,如果您传递2,您将看到您的数字以二进制表示。与十六进制(以16为基数)类似,以36为基数使用字母表示9以外的数字。通过将一个随机数转换为以36为基数,你将得到一堆看似随机的字母和数字。 评论 2013年1月3日20:45
  • 85
    看起来很漂亮,但在少数情况下会生成空字符串!如果随机返回0、0.5、0.25、0.125…将导致空字符串或短字符串。
    – 格塔人
    评论 2013年3月15日19:55
  • 82
    @格塔斯这可以通过以下方式避免(Math.random()+1).toString(36).substring(7); 评论 2013年8月11日17:17
  • 35
    @hacklike crack,重复出现是因为子串(7)取base-36字符串中最低有效部分的数字。到字符串(36)似乎可以将随机数转换为16位基数-36的字符串,但所需的精度为36^16=7.958e24个可能的数字,其中Math.random()的精度仅为4.5电子15.从最有效端取数字.切片(2,5)解决了这个问题:5位数示例
    – 卢克
    评论 2014年12月4日0:48
947

数学.随机对这种事情不好

服务器端

使用节点加密模块-

var crypto=require(“crypto”);var id=crypto.randomBytes(20).toString('hex');//“bb5dc8842ca31d4603d6aa11448d1654”

结果字符串的长度将是您生成的随机字节的两倍;编码为十六进制的每个字节是2个字符。20个字节将是40个十六进制字符。


客户端

使用浏览器的加密模块-

const id=window.crypto.randomUUID()console.log(id)//bd4d099b-3d39-4aad-a59c-c45dfac8eaf0

或者加密.get随机值-

这个crypto.getRandomValues()方法可以获得加密的强随机值。作为参数给出的数组由随机数填充(密码意义上的随机数)。

//dec2hex::Integer->字符串//即0-255->'00'-'f'功能dec2hex(dec){return dec.toString(16).padStart(2,“0”)}//generateId::Integer->字符串函数生成器ID(len){var arr=新的Uint8数组((len||40)/2)window.crypto.getRandomValues(arr)return Array.from(arr,dec2hex).join(“”)}console.log(generateId())//“82defcf324571e70b0521d79cce2bf3fffccd69”console.log(生成ID(20))//“c1a050a4cd1556948d41”

分步控制台示例-

>var arr=new Uint8Array(4)#make 4字节数组(值0-255)>阿珥Uint8Array(4)[0,0,0,0]>窗口.加密加密{精细:精细加密}>window.crypto.getRandomValues()TypeError:Crypto.getRandomValues需要至少1个参数,但只传递了0个>window.crypto.getRandomValues(arr)Uint8Array(4)[235、229、94、228]

对于IE11支持,您可以使用-

(window.crypto ||window.msCrypto).getRandomValues(arr)

有关浏览器覆盖范围,请参阅https://caniuse.com/#feat=getrandomvalues


客户端(旧浏览器)

如果必须支持旧浏览器,请考虑以下内容乌伊德-

const uuid=要求(“uuid”);常量id=uuid.v4();//“110ec58a-a0f2-4ac4-8393-c866d813b8d1”
24
  • 7
    确切地。虽然UUID可以为事物分配ID,但由于这个(可能还有其他)原因,将其用作随机字符串并不是一个好主意。 评论 2015年8月4日17:42
  • 无需.map()选项3中。数组.from(arr,dec2hex).join(“”)===数组.from(arr).map(dec2hex).join('')。感谢您向我介绍这些功能:-) 评论 2017年5月11日19:28
  • 7
    您应该在回答中提到,选项2也需要node.js才能工作,它不是纯javascript。
    – 艾司科
    评论 2018年8月21日11:47
  • 12
    虽然加密更安全,但这实际上并不满足问题的要求,因为它只输出0-9和a-f(十六进制),而不是0-9、a-z、a-z。
    – q杰克
    评论 2018年10月17日19:46
  • 1
    @AneesAhmed777十二月二日提供了一个编码器示例。由您决定如何表示字节。我用你的建议更新了帖子。
    – 木兰
    评论 2020年12月1日17:29
331

简短、简单、可靠

只返回5个随机字符,而不是此处的一些排名靠前的答案。

Math.random().toString(36).slice(2,7);
18
  • 25
    如果…怎么办数学.random().toString(36)返回一个少于5个字符的数字? 评论 2017年1月17日11:42
  • 8
    好吧,这是@Aperçu提出的一个有趣的控诉,我并不是说我发明了这个解决方案,但我已经在我的项目中使用了多年。这与你提到的评论无关。我非常确信,在SO中,最重要的是在正确的地方提供最有用的信息,即使它已经存在于其他地方。幸运的是,似乎至少有51个人发现这个答案很有用,不客气! 评论 2017年3月5日11:10
  • 6
    @rinogo Math.random()可以返回0,但不能返回1developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
    – 米凯普
    评论 2017年8月4日9:54
  • 11
    我运行了这段代码1000000000次,仍然没有得到一个空字符串:jsfiddle.net/mtp5730r我想说,得到空字符串是很安全的。 评论 2018年7月19日13:39
  • 26
    统计上不太可能发生的事件并不安全。如果有人将其用于任何与安全相关的活动,那么他们是在赌博数学.随机未返回0。希望您永远不必调试此事件 评论 2019年3月14日17:26
192

以下是对的改进doubletap的最佳答案。原始版本有两个缺点,现予说明:

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

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

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

数组(N+1).join((Math.random().toString(36)+'00000000000000').slice(2,18)).slic(0,N)

说明:

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

然后这两者是等价的,所以您可以选择对您更直观的:

数组(N).join().split(',').map(function(){returns s.charAt(Math.floor(Math.random()*s.length));}).jjoin('');

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

编辑:

我看起来像量子字节玛丽亚诺提出了与后者类似的解决方案(荣誉!),但我不知怎么错过了。因为它们看起来一眼就不那么短,所以我还是把它留在这里,以防有人真的想要一句单句:-)

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

8
  • 为什么不加1呢?(Math.random()+1).toString(36).substring(7); 评论 2015年1月8日10:00
  • 因为加1并不能解决这里讨论的两个问题。例如,(1).toString(36).substring(7)生成一个空字符串。 评论 2015年1月19日11:36
  • 使用Math.random().toString(36).substring(2,7)给出了一个更像.子字符串(2,n+2) 评论 2015年11月13日13:04
  • Array.apply(null,{length:5}).map(function(){returns s.charAt(Math.floor(Math.random()*s.length));}).join('') 评论 2015年11月13日14:54
  • 这很好,但当在Firefox中以N=16执行时,最后~6位数字最终为零。。。(但它确实满足了OP对5个随机字符的需求。) 评论 2016年6月10日23:15
160

最紧凑的解决方案,因为短于子串。从字符串末尾减法可以避免由随机的,随机的功能:

Math.random().toString(36).slice(-5);

甚至是

(+new Date).toString(36).slice(-5);

更新:添加了另一种方法,使用英国电信运营商协会方法:

btoa(Math.random()).slice(0,5);btoa(+新日期)。切片(-7,-2);btoa(+新日期).substr(-7,5);

//使用Math.random和Base 36:console.log(Math.random().toString(36).slice(-5));//使用新的日期和基准36:console.log((+new Date).toString(36).slice(-5));//使用Math.random和Base 64(btoa):console.log(btoa(Math.random()).slice(0,5));//使用新的日期和基数64(btoa):console.log(btoa(+new Date).slice(-7,-2));console.log(btoa(+new Date).substr(-7,5));

7
  • Math.random().toString(36).slice(-5);-如果数学随机数()收益0?
    – x射线
    评论 2019年7月12日16:00
  • @x射线,你会得到"0";) 评论 2019年7月13日4:13
  • 完全正确。;)如果数学随机数()收益0.5结果是“0.i”。不确定是否存在其他边缘情况。只是想指出,这不是问题的正确答案([a-zA-Z0-9]中的5个字符)。
    – x射线
    评论 2019年7月13日12:27
  • 2
    @x射线,我不想说这是正确的答案,我只是说这是上面@doubletap答案的紧凑版本。我个人使用(+新日期+数学随机数())以防止发生这种情况。无论如何,谢谢你的留言。 评论 2019年7月13日16:39
  • 1
    为什么不使用植物学完全?我对其他答案发表了评论,但使用这个测试用例,您可以看到base64必须提供的64个字符中只有14个字符:[…new Set([…Array(100000)].map(()=>btoa(Math.random()).substr(0,5)).jjoin(“”)].sort()
    – 或段
    评论 2020年11月14日7:34
137

具有的较新版本电子系统6 扩散算子:

[…数组(30)].map(()=>Math.random().toString(36)[2]).join('')

  • 这个30是一个任意数字,您可以选择所需的任何令牌长度
  • 这个36是可以传递给的最大基数numerical.toString(),这意味着所有数字和a-z小写字母
  • 这个2用于从如下所示的随机字符串中选择第三个索引:“0.mfbiohx64i”,我们可以在之后获取任何索引0
6
  • 你能解释一下吗?特别是为什么要将36传递给toString(),为什么要选择第三个元素?
    – 伏扎
    评论 2017年12月5日10:55
  • 很好,但这个解决方案不包括问题要求的[A-Z]字符,只有[A-z0-9] 评论 2020年3月3日13:02
  • @NahuelGreco可以执行[…Array(30)].map(()=>Math.random().toString(36)[2]).join('').toUpperCase() 评论 2020年7月20日0:56
  • @tam.teixeira我认为不是,最初的问题是混合大写,每个字符必须从[a-zA-Z0-9]集合中随机选择。这个答案不能满足这一点。 评论 2020年7月20日15:13
  • 2
    我还要加一个|| '0'所以它又回到了0而不是未定义如果数学随机数()收益0(它永远不会回来1) 评论 2022年8月7日16:29
120

这样应该行得通

函数randomString(len,charSet){charSet=charSet ||'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';var randomString=“”;对于(var i=0;i<len;i++){var randomPoz=数学.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');
5
  • 这里可以找到示例的变体:mediacollege.com/internet/javascript/number/random.html
    – 大卫
    评论 2012年8月31日18:17
  • 2
    还不如减量伦恩直接在中虽然 评论 2013年3月6日14:59
  • 谢谢,我刚刚在下面发布了这个示例的咖啡描述变体:stackoverflow.com/a/26682781/262379 评论 2014年10月31日20:20
  • 如果要公开使用这些元音,那么您可能应该删除元音。熵稍微小一些,但安全得多,因为你不能说出任何可能冒犯别人的话。这就是我喜欢这个的原因,因为我可以发送自己的字符串。干得好。 评论 2017年4月18日18:22
  • 请注意,在Node服务器上,这很简单:crypto.randomBytes(3).toString('hex')(例如,3字节表示6个字符)
    – 胖子
    评论 2022年5月5日18:00
78

函数randomstring(L){var s=“”;var randomchar=函数(){var n=数学地板(Math.random()*62);如果(n<10),则返回n//1-10如果(n<36)返回String.fromCharCode(n+55)//A-Z(A-Z)从CharCode返回String.(n+61)//a-z型}而(s.length<L)s+=randomchar();返回s;}console.log(randomstring(5));

4
  • 我最喜欢这个。您可以很容易地修改以接受额外的参数,并且只返回nums、lowers或caps。我认为没有必要使用超压缩样式而(s.length<L)s+=randomchar(); 评论 2014年1月17日19:24
  • 阿尔索while(L-)(同时(L-))会做到的 评论 2014年6月17日12:30
  • 最好使用更健壮的“A”.charCodeAt(0)而不是神奇的数字55(同样,对于61). 特别是因为,无论如何,在我的平台上,返回的神奇数字是65。该代码也能更好地进行自我记录。 评论 2017年7月10日6:00
  • 我在这里为您的实现创建了一个优化的缩小(小46字节)变体:stackoverflow.com/a/52412162 评论 2018年9月20日7:18
75

随机字符串生成器(Alpha-Numeric|Alpha|Numeric)

/***伪随机字符串生成器* http://stackoverflow.com/a/27872144/383904*默认值:返回随机字母数字字符串* *@param{Integer}len所需长度*@param{String}an可选(字母数字)、“a”(字母)、“n”(数字)*@return{String}*/函数randomString(len,an){an=一个&&an.toLowerCase();var str=“”,i=0,min=an==“a”?10:0,max=an==“n”?10 : 62;对于(;i++<len;){var r=数学随机数()*(max-min)+min<<0;str+=String.fromCharCode(r+=r>9?r<36?55:61:48);}返回str;}console.log(randomString(10));//即:“4Z8iNQag9v”console.log(randomString(10,“a”));//即:“aUkZuHNcWw”console.log(randomString(10,“n”));//即:“9055739230”


虽然上述使用额外的检查A/N、A、N输出,为了更好地理解,让我们将其分解为要点(仅限字母-数字):

  • 创建一个接受参数的函数(随机String结果所需的长度)
  • 创建一个空字符串,如var str=“”;连接随机字符
  • 在循环内部创建兰特索引编号0到61(0..9+A..Z+A..Z=62)
  • 创建一个条件逻辑调整/修复兰特(因为它是0..61)将其增加一些数字(参见下面的示例)以返回正确值字符码数字和相关字符。
  • 在循环内部连接到字符串字符串.fromCharCode(递增rand)

让我们想象一下ASCII字符表范围:

_____0….9 ______ A……….Z ______ A…….Z ___________字符|10||26||26|总计=62个字符48….57 65…….90 97…….122字符代码范围

数学地板(数学随机*62)给出的范围为0..61(我们需要什么)。
让我们修正随机数以获得正确值charCode范围:

|rand | charCode |(0..61)rand+=fix=charCode范围|------+----------+----------+--------------------------------+-----------------+0..9|0..9|48..57|rand+=48=48..57|A..Z|10..35|65..90|兰特+=55/*90-35=55*/=65..90|a..z|36..61|97..122|rand+=61/*122-61=61*/=97..122|

这个有条件操作逻辑从上表中可以看出:

兰德+=兰德>9?(兰特<36?55:61):48;//rand+=真?(对吗?其他55人61人)其他48人;

根据上面的解释,结果如下字母数字片段:

函数randomString(len){var str=“”;//字符串结果for(var i=0;i<len;i++){//循环`len`次var rand=数学地板(Math.random()*62);//随机:0..61var charCode=rand+=rand>9?(兰特<36?55:61):48;//获取正确的charCodestr+=字符串.fromCharCode(charCode);//将字符添加到str}return str;//完成所有循环后,返回连接的字符串}console.log(randomString(10));//即:“7GL9F0ne6t”

或者如果您愿意:

const randomString=(n,r=“”)=>{而(n-)r+=String.fromCharCode((r=Math.random()*62|0,r+=r>9?(r<36?55:61):48);返回r;};console.log(randomString(10))

1
  • 1
    由于我无法识别的原因,x.toString(36)---正如上面的答案中所使用的那样,当我比较两个不同ES版本的应用程序的输出时,并没有可靠地生成相同的字符,这个函数为我修复了这个问题,因为它没有使用.toString()! 评论 2021年2月4日22:13
75

要满足要求[a-zA-Z0-9]和5个字符的长度,请使用

对于浏览器:

btoa(Math.random().toString()).substring(10,15);

对于节点JS:

缓冲区.from(Math.random().toString()).toString(“base64”).substring(10,15);

将出现小写字母、大写字母和数字。

(它与打字兼容)

7
  • 6
    我想,Math.random()可能会导致base64字符串中的字符太少。
    – 莱夫
    评论 2018年6月25日7:57
  • 添加@Leif注释后,只会生成介于1-5封,52封信中只有19封!(大写和小写)要进行测试,只需多次运行,设置它可以查看唯一的字符,然后进行排序。一行代码:[…new Set([…Array(100000)].map(()=>btoa(Math.random()).substr(5,5)).jjoin(“”)].sort()
    – 或段
    评论 2020年11月14日7:19
  • 为什么我们需要toString(字符串)在浏览器示例中? 评论 2022年1月9日14:13
  • 你说得对。无需toString()但因为我想做一些“兼容打字”的事情。所以我就这样离开了。 评论 2022年1月11日19:38
  • 1
    我们可以改用.substing(10,15)吗? 评论 2022年9月27日17:47
45

最简单的方法是:

(新日期%9e6).toString(36)

这将根据当前时间生成5个字符的随机字符串。输出示例为400万吨/年4毫伏904兆瓦1

这方面的问题是,如果在同一秒调用它两次,它将生成相同的字符串。

更安全的方法是:

(0|Math.random()*9e6).toString(36)

这将生成一个4或5个字符的随机字符串,始终不同。示例输出如下30日圆第1轮5914su1a型

在这两种方式中,第一部分生成一个随机数。这个.toString(36)部分将数字转换为以36为基数(字母十进制)的表示形式。

7
  • 我不太确定这是如何回答这个问题的;这是一个已有7年历史的问题,已有许多有效答案。如果你选择提供一个新的答案,你真的应该格外小心,确保你的答案得到很好的解释和记录。
    – 克莱斯
    评论 2015年3月11日22:01
  • 1
    如果您使用Date,为什么不这样使用:(+新日期).toString(36) 评论 2015年7月15日13:47
  • 2
    我想要一个长的随机字符串和一个短的尽可能的例程(用于代码演示),它不需要密码技术上的惊人,只需要生成一些漂亮的随机视觉“fluff”。我最喜欢这个答案(你的第二个),所以谢谢你。我的两美分:我只需少敲一次键就可以打败它,它通常会产生13个随机字符(没有句点):(数学.random()*1e20).toString(36). 评论 2016年2月27日19:11
  • 1
    我对这个答案感到不安的是,它不会使用原来问题中的[A-Z]。 评论 2017年10月11日22:16
  • 1
    “最简单的方法”根本不会创建随机字符串;它创建了高度可预测的字符串,表面上看起来是随机的。 评论 2022年8月27日1:26
38

这里有一些简单的单句。更改新建数组(5)设置长度。

包括0-9a-z

new数组(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.rendom()<.5?“toString”:“toUpperCase”]();});

用于ES6的Codegolfed(0-9a-z)

数组(5).fill().map(n=>(Math.random()*36|0).toString(36)).join('')
0
28

没有最好的方法这样做。只要结果符合您的要求,您可以按自己喜欢的方式进行。为了说明,我创建了许多不同的示例,所有这些示例都应该提供相同的最终结果

本页上的大多数其他答案都忽略了大写字母的要求。

这是我的最快的解决方案可读性最强它基本上与公认的解决方案相同,只是速度稍快一些。

函数readableRandomStringMaker(长度){for(var s='';s.length<length;s+='abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'.charAt(Math.random()*62|0));返回s;}console.log(readableRandomStringMaker(长度));//电子3cbN

这里有一个紧凑,递归可读性差得多的版本:

const compactRandomStringMaker=(length)=>length--&&“abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789”.charAt(Math.random()*62|0)+(compactRandomStringMaker(length||“”);console.log(compactRandomStringMaker(5));//DVudj公司

A类更紧凑的一个衬垫:

数组(5).fill().map(()=>“abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789”.charAt(Math.random()*62)).join(“”)//东经12度

上述变化:

“”“.replaceAll(”“,()=>”abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789“.charAt(Math.random()*62))

这个最紧凑的一行,但效率低且不可读-它添加随机字符并删除非法字符,直到长度为:

((l,f=(p='')=>p.长度<l?f(p+String.fromCharCode(Math.random()*123).replace(/[^a-z0-9]/i,'')):p)=>f())(5)

A类加密安全版本,这是为了紧凑而浪费熵,而且不管怎样都是浪费,因为生成的字符串太短了:

[…crypto.getRandomValues(new Uint8Array(999))].map((c)=>String.fromCharCode(c).replace(/[^a-z0-9]/i,'')).join(“”).substr(0,5)//8平方英尺

或者,如果没有长度参数,它甚至更短:

(f=(p=“”)=>p.长度<5?f(p+String.fromCharCode(Math.random()*123).replace(/[^a-z0-9]/i,'')):p)=>f())()//电动汽车6c9

然后更具挑战性-使用无名递归箭头函数:

((l,s=((l)=>l--&&“abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789”.charAt(数学随机数()*62|0)+(s(l)||“”))=>s(1))(5);//qzal4号机组

这是一个“魔术”变量它在每次访问时提供随机字符:

const c=新类{[Symbol.toPrimitive](){return“abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789”.charAt(Math.random()*62|0)}};console.log(c+c+c~+c+c);//AgMnz公司

上述的简单变体:

const c=()=>“abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789”.charAt(数学.random()*62|0);c()+c()+c()+c()+c();//6卡德夫
26

我知道每个人都已经做对了,但我想尝试以最轻量级的方式(轻量级的代码,而不是CPU):

函数rand(长度,电流){电流=电流?当前:“”;返回长度?rand(--长度,“0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz”.charAt(数学地板(数学.random()*60))+当前):当前;}控制台.log(rand(5));

这需要一点时间来让你回过头来,但我认为这确实说明了javascript的语法有多棒。

  • 23
    如果你想让代码简短,为什么要写电流=电流?当前:“”;当你能写字的时候current=当前|''; 评论 2011年8月8日13:45
  • 10
    由于我们在这里谈论的是微观优化,如果没有必要,我实际上建议完全跳过变量分配:当前|(当前=“”); 评论 2013年12月13日10:36
  • 在使用“nice”但浪费资源的递归算法的同时尝试微优化是没有意义的:-)在Javascript中,for循环仍然是最好的,它大大优于递归,直到在运行时的优化代码方面取得了很大进展。
    – 莫尔
    评论 2019年6月26日9:52
25

生成安全的随机字母数字底座62字符串:

函数生成器UID(长度){return window.btoa(String.fromCharCode(…window.crypto.getRandomValues(new Uint8Array(length*2))).replace(/[+/]/g,“”).substring(0,length);}console.log(生成UID(22));//“yFg3以上v2cE9cKOXd7hHwWp”console.log(生成UID(5));//“YQGzP”

20

如果有人对一次性分配内存的一行程序感兴趣(尽管为了方便起见没有这样的格式)(但请注意,对于小字符串,这确实无关紧要),下面是如何实现的:

Array.apply(0,Array(5)).map(function()){return(函数(字符集){return charset.charAt(数学地板(Math.random()*charset.length))}('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789');}).join(“”)

您可以替换5根据所需字符串的长度。感谢@AriyaHidayat这个帖子对于地图函数无法处理由创建的稀疏数组阵列(5).

1
  • 22
    如果您这样格式化,那么每个javascript程序都是“一行程序” 评论 2013年12月1日14:56
18

如果您正在使用洛达什强调:

var randomVal=_.sample('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',5).join('');
2
  • 9
    Lodash用途_.sampleSize('asdfgh',5).join('')
    – 马洛
    评论 2016年8月24日4:08
  • 5
    这实际上不是一个好的解决方案,因为每个文档每个字符都来自一个唯一的索引。这意味着它不是真正随机的,因为没有字符可以/将永远重复。 评论 2017年11月4日21:44
17
const c='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'const s=[…数组(5)].map(_=>c[~~(Math.random()*c.length)]).join('')
0
16

虽然这个答案与其他答案几乎相似,但不同之处在于它使用了:

  • 重复创建5个字符(可以概括为n个)
  • 代替带正则表达式/./替换这5个字符
  • 公式是从62个字符的a-Za-z0-9字符串中随机选取一个字符

设ans=“x”。重复(5).替换(/./g,c=>“abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789”[数学地板(Math.random()*62)]);控制台.log(ans);

15

这是我创建的方法。
它将创建一个包含大写和小写字符的字符串。
此外,我还包含了创建字母数字字符串的函数。

工作示例:
http://jsfiddle.net/greatbigmassive/vhsxs/(仅阿尔法)
http://jsfiddle.net/greatbigmassive/PJwg8/(字母数字)

函数randString(x){var s=“”;while(s.length<x&&x>0){var r=数学随机数();s+=字符代码中的字符串(数学地板(r*26)+(r>0.5?97:65));}返回s;}

2015年7月升级
这是同样的事情,但更有意义,包括所有字母。

var s=“”;while(s.length<x&&x>0){v=数学随机数()<0.5?32:0;s+=String.fromCharCode(数学.round(Math.random()*((122-v)-(97-v))+(97-v));}
2
  • 使用此函数,您永远无法获得大于“M”的大写字母或小于“n”的小写字母。 评论 2015年1月21日14:21
  • 真的?哦!届时可能会进行更多测试。嗯,然而,考虑到它是一个随机字符串,我们真的不在乎其中有什么字母(只要它们是随机的),那么它仍然可以做我们希望它做的事情,这才是最重要的,但是的,它会提供升级,谢谢。
    – 亚当
    评论 2015年7月27日11:50
15

一个衬垫:

数组(15).fill(null).map(()=>Math.random().toString(36).substr(2)).join(“”)//输出:0h61cbpw96y83qtnuwme5lxk1i70a6o5r5lckfcyh1dl9fffydcfxddd69ada9tu9jvqdx864xj1ul3wtfztmh2oz2vs3mv6ej0fe58ho1cftkjcuyl2lfkmxlwua83ibotxqc4guyuvrvtf60naob26t6swzpil
  • 要使其更短,请在中更改参数阵列(15)设置为较小的值。例如。:阵列(4). 评论 2020年4月3日18:40
  • 我真的很喜欢这个简单明了的解决方案。它生成15个介于0和1之间的随机数,生成十六进制,然后删除前两个字符。最后,它将所有这些合并在一起。
    – 西斯卡
    评论 2020年5月11日20:17
  • 错误的解决方案,不会生成大写字符。 评论 2021年7月31日16:20
15

改进了@Andrew上面的回答:

数组.from({length:1},()=>Math.random().toString(36)[2]).join('');

以36为基数的随机数转换是不一致的,所以选择一个索引可以修复这个问题。您可以使用所需的精确长度更改字符串的长度。

0
14

假设您使用内衣只需两行就可以优雅地生成随机字符串:

var possible=“ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789”;var random=_.sample(可能,5).join('');
1
  • 6
    这将使返回的值具有所有唯一的字符。此外,字符串的长度限制为var可能的长度。
    – 叶甫
    评论 2016年11月21日1:37
13
函数randomString(strLength,charSet){var结果=[];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.

4
  • 对我来说,这总是生成随机字符串strLength-1:-/ 评论 2013年11月22日11:43
  • 4
    正在从切换--strLength(字符串长度)str长度--帮我修好了。 评论 2013年11月22日11:43
  • @我冒昧地修改了明显的错误。它是str长度--后缀,而不是前缀。
    – 胖子
    评论 2022年5月5日17:31
  • 谢谢你,先生。将其包装在一个函数中,使其易于复制/粘贴❤️ 评论 2022年8月6日9:24
11

快速改进的算法。不保证统一(见注释)。

函数getRandomId(长度){if(!长度){返回“”;}常量可能='EFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvxyz0123456789';let数组;if(self中的'Uint8Array'和self&&length中的'crypto'<=65536){array=新Uint8Array(长度);self.crypto.getRandomValues(数组);}其他{array=新数组(长度);for(设i=0;i<长度;i++){array[i]=数学地板(Math.random()*62);}}让结果=“”;for(设i=0;i<长度;i++){result+=可能。charAt(array[i]%62);}返回结果;}
2
  • 4
    答案很好,但概率并不一致。有62个可能的字符和加密.get随机值返回256个唯一值之一。因为256不除以62,所以你最终获得字符A-H的概率略高。我认为最好的解决方案是像YouTube那样,只添加2个额外的字符(可能-_)到字符集。总之,干得好-这个答案需要更多的爱:)
    – 特乌
    评论 2017年5月19日12:07
  • 添加-and是一个好主意,因为它将为您提供完整的url-safe base64集合
    – 考伯特
    评论 2017年12月14日23:55
10

这个小技巧怎么样?

var possible=“ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnomqrstuvxyz0123456789”;var字符串长度=5;函数pickRandom(){return possible[Math.floor(Math.random()*possible.length)];}var randomString=Array.apply(null,Array(stringLength)).map(pickRandom).jjoin('');

你需要阵列应用这样可以将空数组变为未定义数组。

如果您正在为ES2015编码,那么构建阵列要简单一些:

var randomString=Array.from({length:stringLength},pickRandom).join('');
10

您可以循环遍历项目数组,并将其递归添加到字符串变量中,例如,如果您想要一个随机DNA序列:

函数randomDNA(len){len=长度||100var nuc=新数组(“A”、“T”、“C”、“G”)var i=0var n=0s=“”while(i<=len-1){n=数学地板(Math.random()*4)s+=nuc[n]我++}返回s}console.log(randomDNA(5));

10

不区分大小写的字母数字字符:

函数randStr(len){设s='';while(s.length<len)s+=Math.random().toString(36).substr(2,len-s.length);返回s;}//使用console.log(randStr(50));

此函数的优点是可以获得不同长度的随机字符串,并确保字符串的长度。

区分大小写的所有字符:

函数randStr(len){设s='';while(len--)s+=String.fromCodePoint(Math.floor(Math.random()*(126-33)+33));返回s;}//用法console.log(randStr(50));

自定义字符

函数randStr(len,chars='abc123'){设s='';while(len--)s+=chars[Math.floor(Math.random()*chars.length)];返回s;}//使用console.log(randStr(50));控制台.log(randStr(50,'abc'));console.log(randStr(50,'aab'));//a多于b

1
  • 这个答案更适合我的用例。如果您可以添加var可能就像公认的答案一样,函数的结果更具可配置性。 评论 2018年10月11日11:40
9

回应的问题“我需要随机字符串”问题(无论用什么语言)实际上每个解决方案都使用有缺陷的主要规范字符串长度这些问题本身很少揭示为什么需要随机字符串,但我想挑战一下,你很少需要长度为8的随机字符串。你总是需要一些唯一字符串例如,出于某种目的用作标识符。

有两种主要方法可以获得严格唯一字符串:确定性(非随机)和存储/比较(繁重)。我们该怎么办?我们放弃了鬼魂。我们一起去概率唯一性而不是。也就是说,我们接受字符串不唯一的风险(无论多么小)。这就是理解碰撞概率都很有帮助。

因此,我将把不变的需求重新表述为需要一些数量的字符串,重复的风险很小。作为一个具体的例子,假设您希望生成500万个ID。您不想存储和比较每个新字符串,并且希望它们是随机的,因此您会承担一些重复的风险。例如,让我们假设重复的风险不到万亿分之一。那么你需要多长的绳子?嗯,这个问题没有具体说明,因为它取决于使用的字符。但更重要的是,它被误导了。您需要的是字符串熵的规范,而不是字符串长度的规范。熵可以直接与某些字符串中重复的概率相关。字符串长度不能。

这就是图书馆喜欢的地方条目字符串可以提供帮助。要生成在500万个字符串中重复的概率小于万亿分之一的随机ID,请使用熵弦:

从“Entropy-string”导入{Random,Entropy}const random=新随机()常量位=熵位(5e6,1e12)const字符串=random.string(位)

“44hTNghjNHGGRHqH9”

熵弦默认情况下使用32个字符的字符集。还有其他预定义的字符集,您也可以指定自己的字符。例如,生成具有与上述相同熵但使用十六进制字符的ID:

从'导入{Random、Entropy、charSet16}/熵弦const random=新随机(charSet16)常量位=熵位(5e6,1e12)const字符串=random.string(位)

“27b33372ade513715481f”

注意字符串长度的差异是由于所使用的字符集中的字符总数的差异造成的。在指定数量的潜在字符串中重复的风险是相同的。字符串长度不是。最重要的是,重复的风险和字符串的潜在数量是明确的。不再猜测字符串长度。

1
  • 谢谢!你的评论让我意识到我不应该随意生成ID。看起来像是纳米级的熵弦看起来对我来说也一样好。
    – 海拔_H
    评论 2020年12月4日23:18

不是你想要的答案吗?浏览标记的其他问题问你自己的问题.