JavaScript 中的随机字母数字字符串

Random alpha-numeric string in JavaScript?

本文关键字:数字 数字字符 字符串 随机 JavaScript      更新时间:2023-09-26

JavaScript 中生成随机字母数字(大写、小写和数字)字符串以用作可能唯一标识符的最短方法(在合理范围内)是什么?

我刚刚发现这是一个非常好和优雅的解决方案:

Math.random().toString(36).slice(2)

有关此实现的说明:

  • 这将生成长度介于 0 到 12 个字符之间的任何字符串,通常为 11 个字符,因为浮点字符串化会删除尾随零。
  • 它不会生成大写字母,只会生成小写字母和数字。
  • 因为随机性来自Math.random(),输出可能是可预测的,因此不一定是唯一的。
  • 即使假设一个理想的实现,输出最多有52位熵,这意味着在生成大约70M个字符串后,你可以期待一个重复的。

如果你只想允许特定的字符,你也可以这样做:

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

更新:单行解决方案,用于随机 20 个字符(字母数字小写):

Array.from(Array(20), () => Math.floor(Math.random() * 36).toString(36)).join('');

或用lodash更短:

_.times(20, () => _.random(35).toString(36)).join('');

JAR 建议的另一种答案变体。罐豆

(Math.random()*1e32).toString(36)

通过更改乘法器1e32您可以更改随机字符串的长度。

或者建立在 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

这更干净

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

Math.random().toString(36).substr(2, 5)
function randomString(len) {
    var p = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    return [...Array(len)].reduce(a=>a+p[~~(Math.random()*p.length)],'');
}

总结:

  1. 创建一个我们想要大小的数组(因为在javascript中没有range(len)等效的数组。
  2. 对于数组中的每个元素:从p中选择一个随机字符并将其添加到字符串中
  3. 返回生成的字符串。

一些解释:

[...Array(len)]

Array(len)

或 new Array(len) 创建一个带有未定义指针的数组。 单行本将更难实现。 Spread 语法方便地定义了指针(现在它们指向未定义的对象!

.reduce(

在本例中,将数组缩减为单个字符串。reduce功能在大多数语言中都很常见,值得学习。

a=>a+...

我们正在使用箭头函数。

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)这是在 JavaScript 中获取随机整数的事实标准。 ~ 是 JavaScript 中的按位 NOT 运算符。 ~~是一种更短,有时可以说更快,绝对更有趣的表达方式 Math.floor( 这里有一些信息

我认为以下是允许给定长度的最简单解决方案:

Array(myLength).fill(0).map(x => Math.random().toString(36).charAt(2)).join('')

这取决于箭头函数语法。

表示 32 个字符:

for(var c = ''; c.length < 32;) c += Math.random().toString(36).substr(2, 1)

随机字符:

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/

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

随机密钥生成器

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

当我看到这个问题时,我想到了什么时候必须生成UUID。我不能相信代码,因为我确定我在stackoverflow上找到了它。如果您不想要字符串中的破折号,请取出破折号。这是函数:

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/

此函数应提供任意长度的随机字符串。

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是否使用尾部调用优化

一个简单的函数,需要长度

getRandomToken(len: number): string {
  return Math.random().toString(36).substr(2, len);
}

Ff 你通过 6 它将生成 6 位字母数字

漂亮而简单,不限于一定数量的字符:

let len = 20, str = "";
while(str.length < len) str += Math.random().toString(36).substr(2);
str = str.substr(0, len);

下面是生成随机字符串字母表的简单代码。看看这段代码是如何工作的。

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

可以使用 lodash uniqueId:

    _.uniqueId([prefix=''])

生成唯一 ID。如果给出了前缀,则会将 ID 附加到其中。

我使用了@Nimphious出色的第二种方法,发现偶尔返回的字符串是数字 - 而不是字母数字。我使用的解决方案是使用 !isNaN 进行测试,并使用递归再次调用函数。何苦?我正在使用这个函数来创建对象键,如果所有键都是字母数字,则所有键都可以正确排序,但是如果您使用数字作为键与字母数字(字符串)混合在对象中循环将产生与原始顺序不同的顺序。

function newRandomString(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 += '0123456789';
  var result = '';
  for (var i = length; i > 0; --i) result += mask[Math.floor(Math.random() * 
  mask.length)];
  /*    
        we need a string not a number !isNaN(result)) will return true if '1234' or '3E77'
        because if we're looping through object keys (created by newRandomString()) and 
        a number is used and all the other keys are strings then the number will 
        be first even if it was the 2nd or third key in object
  */
  //use recursion to try again
  if(!isNaN(result)){
    console.log('found a number....:'+result);
    return newRandomString(length, chars)
  }else{
    return result;
  }
};
var i=0;
while (i < 1000) {
  var a = newRandomString(4, '#$aA');
  console.log(i+' - '+a);
  //now we're using recursion this won't occur
  if(!isNaN(a)){
    console.log('=============='+i+' - '+a);
  }
  i++;
}
console.log('3E77:'+!isNaN('3E77'));//true
console.log('1234:'+!isNaN('1234'));//true
console.log('ab34:'+!isNaN('ab34'));//false

在查看了此问题的答案和其他来源的解决方案后,这是最简单的解决方案,同时允许修改包含的字符和选择返回结果的长度。

// generate random string of n characters
function randomString(length) {
    const characters = '0123456789abcdefghijklmnopqrstuvwxyz'; // characters used in string
    let result = ''; // initialize the result variable passed out of the function
    for (let i = length; i > 0; i--) {
        result += characters[Math.floor(Math.random() * characters.length)];
    }
    return result;
}
console.log(randomString(6));

我需要更长的字符串,我喜欢@JAR。JAR.豆子优雅的回答。

这是一个可调节的衬里,可生成更长的字符串。

Array(100).fill().map(z=>Math.random().toString(36).slice(2)).join("")

您甚至可以更改数字100以调整随机生成的字符串的长度

使用 md5 库:https://github.com/blueimp/JavaScript-MD5

最短的路:

md5(Math.random())

如果要将大小限制为 5:

md5(Math.random()).substr(0, 5)

如果要指定任何字符集,例如 base64 字符,而不在"abcd..."中键入每个字符字符串,您可以这样做:

const chars = [['0', 10], ['a', 26], ['A', 26], ['-'], ['_']]
  .flatMap(([c, length=1]) =>
    Array.from({length}, (_,i) => String.fromCharCode(c.charCodeAt(0)+i)))
const gen = length => Array.from({length},
  () => chars[Math.random()*chars.length|0]).join('')
console.log(chars.join(''))
console.log(gen(10))