在JavaScript中生成随机字符串/字符

Tom Lehman 1593 javascript random

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

使用JavaScript执行此操作的最佳方法是什么?

csharptest.n.. 2189

我认为这对你有用:

function makeid(length) {
   var result           = '';
   var characters       = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
   var charactersLength = characters.length;
   for ( var i = 0; i < length; i++ ) {
      result += characters.charAt(Math.floor(Math.random() * charactersLength));
   }
   return result;
}

console.log(makeid(5));

  • 这对于短字符串很好,但要注意,在这样的字符串上使用`+ =`会导致它具有O(n ^ 2)行为.如果要创建更长的字符串,则应创建一个单独的字符数组,并在最后将它们连接在一起. (108认同)
  • @dan_waterworth在几乎*任何*案件中它可能无关紧要:http://www.codinghorror.com/blog/2009/01/the-sad-tragedy-of-micro-optimization-theater.html (90认同)
  • @JonathanPaulson*给我看数字*.使用jsperf链接或http://jsperf.com/sad-tragedy-of-microoptimization或http://www.sitepen.com/blog/2008/05/09/string-performance-an-analysis查看上一条评论/等等,此问题仅涉及5个连接. (16认同)
  • @dan_waterworth,实际上,`+ =`由于某种原因通常更快,甚至在循环中使用 - http://jsperf.com/join-vs-concatenation (7认同)
  • @codenamejames请*在密码腌制中使用*.它只是伪随机不安全.假设您正在使用Node(如果您在客户端进行腌制,我甚至不确定从哪里开始),请使用[`crypto`](http://nodejs.org/api/crypto.html). (7认同)
  • 它可能看起来不对,但是`floor`是不需要的:for(var text =''; text.length <5;)text + = possible.charAt(Math.random()*possible.length) (3认同)
  • @AlexReece那个链接没有说出你的想法.做一百万次"a"+"b"就可以了.做一次+ ="b"一百万次不是. (2认同)
  • 所以我只是碾压了一些数字(关于```1000万```时间)和5个字符你得到一个```0.05%```复制相当一致,当你把字符提升到%%关于```0.0001%```.我计划在我的密码腌制中使用它,我将使用10个字符兰特字符串,我认为它将是完美的! (2认同)

doubletap.. 2186

let r = Math.random().toString(36).substring(7);
console.log("random", r);

注意:上述算法有以下缺点:

  • 它将生成0到6个字符之间的任何位置,因为在对浮点进行字符串化时会删除尾随零.
  • 它很大程度上取决于用于字符串化浮点数的算法,这种算法非常复杂.(参见文章"如何准确打印浮点数".)
  • Math.random()可能会产生可预测的("随机的"但不是真正随机的)输出,具体取决于实现方式.当您需要保证唯一性或不可预测性时,生成的字符串不适合.
  • 即使它产生了6个均匀随机,不可预测的字符,由于生日悖论,你可能会在生成大约50,000个字符串之后看到重复.(sqrt(36 ^ 6)= 46656)

  • `Math.random().toString(36).substr(2,5)`,因为`.substring(7)`导致它长于5个字符.满分,还在! (262认同)
  • 盖伊,这几乎没用.运行它只有1000000次,你通常会重复出现110000次:var values = {},i = 0,duplicateCount = 0,val; while(i <1000000){val = Math.random().toString(36).substring(7); if(values [val]){duplicateCount ++; } values [val] = 1; 我++; } console.log("TOTAL DUPLICATES",duplicateCount); (83认同)
  • @Scoop javascript中数字类型的`toString`方法采用可选参数将数字转换为给定的基数.例如,如果你传递两个,你会看到你的数字用二进制表示.类似于十六进制(基数16),基数36使用字母来表示超过9的数字.通过将随机数转换为基数36,您将得到一堆看似随机的字母和数字. (77认同)
  • 看起来很漂亮,但在少数情况下会产生空字符串!如果随机返回0,0.5,0.25,0.125 ......将导致空或短字符串. (72认同)
  • @gertas这可以通过`(Math.random()+ 1).toString(36).substring(7); (65认同)
  • @hacklikecrack,重复出现是因为`substring(7)`从base-36字符串的最不重要部分获取数字.`toString(36)`似乎将随机数转换为16位base-36字符串,但是这需要的精度为36 ^ 16 = 7.958e24个可能的数字,其中Math.random()的精度仅为[ 4.5e15](http://stackoverflow.com/questions/3344447/math-random-question).使用`.slice(2,5)`取最重要的数字来解决这个问题:[5位数示例](http://jsfiddle.net/dbbfmfdL/) (32认同)
  • 喜欢它,但他需要[a-zA-Z] (15认同)
  • `(+ new Date*Math.random()).toString(36).substring(0,5)` (9认同)
  • 好的解决方案 但是,我宁愿使用切片,因此字符数与给定参数匹配.`的Math.random().的toString(36).slice(-5)` (7认同)
  • 总而言之,使用@GeorgeReith和dragon技术的最终脚本是:(Math.random()+1).toString(36).substr(2,5).它会停止字符串为空并将其限制为5个字符. (5认同)
  • 我不知道它是否无用,但hacklikecrack完全是在说实话.csharptest.net的算法产生的重复数据少得多.如果你将数字位数增加到8,你会发现重复数字会降为零.谢谢你@hacklikecrack (4认同)
  • "0"修正:`('0000'+ Math.random().toString(36).replace('.','')).substr(-5);` (3认同)
  • 这会产生更长的随机数:(Math.PI*Math.max(0.01,Math.random())).toString(36).substr(2,5); (2认同)
  • @ william44isme:如果Math.random()返回0.25,那么上面将评估为`(1.25).toString(36).substr(2,5)`,它将等于`9` - 所以它仍然不起作用.我这样做:`函数randomString(){var i =''; while(i.length <5){i = Math.random().toString(36).slice(2);}; 回归我; }`,它给我一串至少5的字符串 (2认同)
  • 该解决方案仅部分回答了这个问题.它将生成一个随机的部分字符串`[a-z0-9]`.它不包括大写字母.尽管如此,仍然是一个非常好的技巧! (2认同)
  • 这可能无法在较新版本的Chrome中按预期工作(http://thenextweb.com/google/2015/12/17/google-chromes-javascript-engine-finally-returns-actual-random-numbers/#gref) (2认同)

Thank you.. 390

Math.random对这种事情不好

选项1

如果你能够在服务器端执行此操作,只需使用加密模块即可

var crypto = require("crypto");
var id = crypto.randomBytes(20).toString('hex');

// "bb5dc8842ca31d4603d6aa11448d1654"

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


选项2

如果你必须做这个客户端,也许尝试uuid模块

var uuid = require("uuid");
var id = uuid.v4();

// "110ec58a-a0f2-4ac4-8393-c866d813b8d1"

选项3

如果你必须在客户端做这个并且你不必支持旧的浏览器,你可以做到没有依赖

// 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"

  • 你应该在答案中提到选项2也需要node.js才能工作,它不是纯粹的javascript. (4认同)
  • 究竟。尽管UUID可以为事物分配ID,但出于这个(可能还有其他)原因,将其用作一串随机字符并不是一个好主意。 (3认同)
  • 尽管在密码学上更安全,但这实际上不能满足问题的要求,因为它仅输出0-9和af(十六进制),而不输出0-9,az,AZ。 (3认同)

Silver Ringv.. 162

简短,轻松,可靠

返回5个随机字符,而不是这里找到的一些最高评分的答案.

Math.random().toString(36).substr(2, 5);

  • 如果`Math.random()。toString(36)`返回一个少于5个字符的数字怎么办? (5认同)
  • @rinogo Math.random()可以返回0而不是1 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random (5认同)
  • 我运行此代码1,000,000,000次仍然没有得到一个空字符串:jsfiddle.net/mtp5730r我会说你得到一个空字符串非常安全. (4认同)
  • 嗯,这是来自@Aperçu的一个有趣的起诉书,我并不是说我发明了解决方案,但我已经在我的项目中使用它多年了.它与你提到的评论无关.而且我很确定在最重要的地方,最重要的信息是在正确的地方,即使它已经存在于其他地方.幸运的是,似乎至少有51个人发现这个答案很有用,欢迎你! (3认同)
  • 为了避免在Math.random()返回0的情况下得到空字符串,你可以使用`function getRandomString(){var result =''; while(!result)result = Math.random().toString(36).substring(2); 返回结果; };` (3认同)
  • 从统计上讲不太可能发生的事件并不会使它安全。如果有人将其用于任何与安全相关的活动,他们正在赌博'Math.random'的可能性不返回0。希望您永远不必调试此事件 (3认同)
  • 这并不总是返回5个字符。例如,((0.5).toString(36).substr(2,5)`产生`“ i”`)。 (2认同)

amichair.. 152

这是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)

说明:

  1. 选择范围[0,1)中的随机数,即0(包括)和1(不包括)之间的随机数.
  2. 将数字转换为base-36字符串,即使用字符0-9和az.
  3. 用零填充(解决第一个问题).
  4. 切掉领先的'0' 前缀和额外的填充零.
  5. 重复字符串足够多次以使其中至少包含N个字符(通过将空字符串与用作分隔符的较短随机字符串连接起来).
  6. 从字符串中精确切割N个字符.

进一步思考:

  • 这个解决方案不使用大写字母,但几乎在所有情况下(没有双关语)都没关系.
  • 在Chrome中测量原始答案中N = 16的最大字符串长度.在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('');

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

编辑:

我好像是qubyte,Martijn de Milliano提出了类似于后者的解决方案(kudos!),我不知何故错过了.因为它们一目了然看起来不那么短,所以无论如何我都会把它留在这里以防有人真的想要一个单线:-)

此外,在所有解决方案中将'new Array'替换为'Array'以减少更多字节.


Valentin.. 101

最紧凑的解决方案,因为slice比较短substring.从字符串末尾减去允许避免random函数生成的浮点符号:

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

甚至

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

btoa(Math.random()).slice(0, 5);
btoa(+new Date).slice(-7, -2);
btoa(+new Date).substr(-7, 5);


CaffGeek.. 93

这样的事情应该有效

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');


kennebec.. 71

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不包括字符列表.:) (15认同)
  • 同时`while(L - )`会这样做 (3认同)

Roko C. Bulj.. 48

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

/**
 * 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;
}
randomString(10);        // "4Z8iNQag9v"
randomString(10, "A");   // "aUkZuHNcWw"
randomString(10, "N");   // "9055739230"

玩得开心.jsBin演示


虽然上面使用了对所需(A/N,A,N)输出的附加检查,但是为了更好地理解, 我们将其分解为基本要素(仅限字母数字):

  • 创建一个接受参数的函数(随机字符串结果的所需长度)
  • 创建一个空字符串,var str = "";以便连接随机字符
  • 在循环内创建一个rand0到61 索引号(0..9 + A..Z + a..z = 62)
  • 创建一个条件逻辑调整/修复rand(因为它是0..61)将它递增一些数字(参见下面的例子)以获得正确的CharCode数字和相关的字符.
  • 循环内部连接到str一个String.fromCharCode( incremented rand )

让我们看一下Character表及其范围:

_____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(我们需要的)范围. 如何修复(递增)随机以获得正确的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 ;

如果您按照上述说明操作,则应该能够创建此字母数字代码段:

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;
}


Or Duan.. 46

带有es6 扩展运算符的更新版本:

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

  • 30是任意数字,您可以选择任何您想要的令牌长度
  • 36是您可以传递给numeric.toString()的最大基数,这意味着所有数字和az小写字母
  • 2是用来接从它看起来像这样的随机字符串的第3号:"0.mfbiohx64i",我们可以采取任何索引后0.

  • 这是最好的解决方案 (2认同)

MasqueradeCi.. 31

最简单的方法是:

(new Date%9e6).toString(36)

这将根据当前时间生成5个字符的随机字符串.示例输出是4mtxj4mv904mwp1

这个问题是如果你在同一秒钟上调用它两次,它将生成相同的字符串.

更安全的方式是:

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

这将生成一个4或5个字符的随机字符串,总是不同的.示例输出类似于30jzm1r5914su1a

在两种方式中,第一部分生成随机数.该.toString(36)部分将数字转换为它的base36(alphadecimal)表示.


bendytree.. 20

这里有一些简单的衬里.更改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"]();});


小智.. 19

我知道每个人都已经把它弄好了,但我觉得可以用最轻量级的方式去做这个(代码轻,不是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));

我们需要一些时间来解决这个问题,但我认为它确实展示了javascript的语法是多么棒.

  • 如果你试图保持代码简短,为什么写`current = current?current:'';`什么时候可以写`current = current || ""'; (20认同)
  • 因为我们在这里讨论微优化,所以我实际上建议完全跳过变量赋值,如果没有必要:`current || (current ='');` (8认同)

vineet.. 16

如果你正在使用Lodash下划线,那么就这么简单:

var randomVal = _.sample('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 5).join('');

  • Lodash使用`_.sampleSize('asdfgh',5).join('')` (6认同)
  • 这实际上不是一个好的解决方案,因为_per docs_每个字符都来自唯一索引。这意味着它不是真正随机的,因为没有字符可以/将不会重复。 (2认同)

Adam.. 13

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

工作示例:
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)));
}


Martijn de M.. 12

如果有人对单线程感兴趣(虽然为了方便起见没有格式化),一次分配内存(但请注意,对于小字符串,它确实无关紧要)以下是如何做到这一点:

Array.apply(0, Array(5)).map(function() {
    return (function(charset){
        return charset.charAt(Math.floor(Math.random() * charset.length))
    }('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'));
}).join('')

您可以用5所需字符串的长度替换.感谢@AriyaHidayat在这篇文章中解决了map函数不能处理由创建的稀疏数组Array(5).

  • 如果您将其格式化,则每个javascript程序都是"单行" (13认同)

tiktak.. 12

假设您使用underscorejs,可以在两行中优雅地生成随机字符串:

var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var random = _.sample(possible, 5).join('');

  • 这将使返回的值具有所有唯一的字符.此外,字符串的长度限制为可能的长度. (6认同)

Sergio Cabra.. 12

满足要求[a-zA-Z0-9]和长度= 5使用

btoa(Math.random()).substr(5, 5);

将出现小写字母,大写字母和数字.


yaroslav.. 8

快速改进的算法.不保证统一(见评论).

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;
}

  • 很好的答案,但概率不均匀.有62个可能的字符,`crypto.getRandomValues`返回256个唯一值之一.因为256没有除以62,所以最终获得字符AH的概率略高.我认为最好的解决方案是做YouTube所做的事情,只需在字符集中添加2个附加字符(可能是`-`和`_`).无论如何,伟大的工作 - 这个答案需要更多的爱:) (2认同)

小智.. 7

您可以遍历项目数组并以递归方式将它们添加到字符串变量中,例如,如果您需要随机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));


Gajus.. 6

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.

  • 从`--strLength`切换到`strLength - 为我修正它. (2认同)

小智.. 6

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

获得严格唯一的字符串有两种主要方法:确定性(不是随机的)和存储/比较(繁琐的)。我们做什么?我们放弃了幽灵。我们代之以概率唯一性。也就是说,我们接受我们的字符串存在唯一性的风险(但很小)。在这里,了解碰撞概率很有帮助。

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

这就是像EntropyString这样的库可以提供帮助的地方。要生成随机ID,该随机ID在500万个字符串中重复的概率小于1万亿,请使用以下方法entropy-string

import {Random, Entropy} from 'entropy-string'

const random = new Random()
const bits = Entropy.bits(5e6, 1e12)

const string = random.string(bits)

“ 44hTNghjNHGGRHqH9”

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

import {Random, Entropy, charSet16} from './entropy-string'

const random = new Random(charSet16)
const bits = Entropy.bits(5e6, 1e12)

const string = random.string(bits)

“ 27b33372ade513715481f”

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


ravishi.. 6

我没有找到支持小写和大写字符的干净解决方案.

小写仅支持:

Math.random().toString(36).substr(2, 5)

在该解决方案的基础上支持小写和大写:

Math.random().toString(36).substr(2, 5).split('').map(c => Math.random() < 0.5 ? c.toUpperCase() : c).join('');

更改5substr(2, 5)调整到你需要的长度.


小智.. 5

这肯定有用

<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>


小智.. 5

这样的事情怎么样:Date.now().toString(36) 不是很随机,但是每次调用时都很短而且很独特。


归档时间:

查看次数:

1225012 次

最近记录:

1 年,6 月 前