我想要一个5个字符串,该字符串由从集合中随机选择的字符组成[a-zA-Z0-9]
。
用JavaScript做到这一点的最佳方法是什么?
Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
我想要一个5个字符串,该字符串由从集合中随机选择的字符组成[a-zA-Z0-9]
。
用JavaScript做到这一点的最佳方法是什么?
Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
Answers:
我认为这将为您工作:
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)行为。如果要创建更长的字符串,则应创建一个由单个字符组成的数组,并在最后将它们连接在一起。
+=
由于某些原因通常会更快,甚至在循环内使用-jsperf.com/join-vs-concatenation
crypto
改用。
let r = Math.random().toString(36).substring(7);
console.log("random", r);
注意:以上算法具有以下缺点:
Math.random()
根据实现的不同,可能会产生可预测的(“看上去很随机”但不是真正随机的)输出。当您需要保证唯一性或不可预测性时,结果字符串不适合。Math.random().toString(36).substr(2, 5)
,因为.substring(7)
长度超过5个字符。满分!
toString
javascript中数字类型的方法采用可选参数,以将数字转换为给定的底数。例如,如果您传递两个,则您将看到以二进制表示的数字。与十六进制(基数16)相似,基数36使用字母来表示9以外的数字。通过将随机数转换为基数36,您将得到一系列看似随机的字母和数字。
(Math.random() + 1).toString(36).substring(7);
选项1
如果您能够在服务器端执行此操作,则只需使用crypto模块-
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"
有关更多信息crypto.getRandomValues
-
该
crypto.getRandomValues()
方法可让您获得加密强度高的随机值。作为参数给出的数组填充有随机数(其密码含义随机)。
这是一个小的控制台示例-
> 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支持,您可以使用-
(window.crypto || window.msCrypto).getRandomValues(arr)
有关浏览器的覆盖范围,请参见https://caniuse.com/#feat=getrandomvalues
.map()
选项3中不需要。Array.from(arr, dec2hex).join('')
=== Array.from(arr).map(dec2hex).join('')
。感谢您向我介绍这些功能:-)
require
模块不是只能在服务器端使用吗?
返回恰好5个随机字符,与此处找到的一些评价最高的答案相反。
Math.random().toString(36).substr(2, 5);
Math.random().toString(36)
返回少于5个字符的数字怎么办?
function getRandomString() { var result = ''; while (!result) result = Math.random().toString(36).substring(2); return result; };
这是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)
说明:
进一步的想法:
更新:
这是我想到的其他几个功能样式的单线纸。它们与上述解决方案的不同之处在于:
因此,假设您选择的字母是
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提出了与后者类似的解决方案(赞!),我不知为何错过了。由于它们看起来并不那么短,所以我还是把它留在这里,以防有人真的想要单线:-)
同样,在所有解决方案中都将“ new Array”替换为“ Array”以节省更多字节。
(Math.random()+1).toString(36).substring(7);
Math.random().toString(36).substring(2,7)
给出的预期结果更像是.substring(2, n+2)
Array.apply(null, {length: 5}).map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('')
最紧凑的解决方案,因为slice
它比短substring
。从字符串的末尾减去可以避免该random
函数生成的浮点符号:
Math.random().toString(36).slice(-5);
甚至
(+new Date).toString(36).slice(-5);
更新:添加了另一种使用btoa
方法:
btoa(Math.random()).slice(0, 5);
btoa(+new Date).slice(-7, -2);
btoa(+new Date).substr(-7, 5);
// Using Math.random and Base 36:
console.log(Math.random().toString(36).slice(-5));
// Using new Date and Base 36:
console.log((+new Date).toString(36).slice(-5));
// Using Math.random and Base 64 (btoa):
console.log(btoa(Math.random()).slice(0, 5));
// Using new Date and Base 64 (btoa):
console.log(btoa(+new Date).slice(-7, -2));
console.log(btoa(+new Date).substr(-7, 5));
Math.random().toString(36).slice(-5);
-如果Math.random()
退货0.0
怎么办?
"0"
;)
Math.random()
返回,0.5
则结果为"0.i"
。不知道是否还有其他情况。只是想指出这不是问题的正确答案([a-zA-Z0-9]中的5个字符)。
(+new Date + Math.random())
用来防止这种情况。无论如何,感谢您的来信。
这样的事情应该工作
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');
len
直接在while
环
带有es6 传播算子的较新版本:
[...Array(30)].map(() => Math.random().toString(36)[2]).join('')
30
是任意的号码,你可以选择你想要的任何标记长度36
是最大基数数可以传递给numeric.toString() ,这意味着所有的数字和AZ小写字母2
是用来接从它看起来像这样的随机字符串这是第3指标:"0.mfbiohx64i"
,我们可以采取任何索引后0.
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));
while(s.length< L) s+= randomchar();
while(L--)
将这样做
'A'.charCodeAt(0)
而不是幻数55
(同样适用于61
)。特别是因为无论如何在我的平台上返回的幻数是65
。该代码也将更好地自我记录。
/**
* Pseudo-random string generator
* http://stackoverflow.com/a/27872144/383904
* Default: return a random alpha-numeric string
*
* @param {Integer} len Desired length
* @param {String} an Optional (alphanumeric), "a" (alpha), "n" (numeric)
* @return {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;
}
console.log(randomString(10)); // i.e: "4Z8iNQag9v"
console.log(randomString(10, "a")); // i.e: "aUkZuHNcWw"
console.log(randomString(10, "n")); // i.e: "9055739230"
尽管以上内容针对所需的A / N,A,N输出使用了其他检查,但为了更好地理解,我们将其分解为基本内容(仅字母数字)。
var str = "";
以连接随机字符rand
从0到61 的索引号(0..9 + A..Z + a..z = 62)rand
(因为它是0..61),将其递增某个数字(请参见下面的示例),以获取正确的CharCode
数字和相关的Character。str
一个String.fromCharCode( incremented rand )
让我们看一下ASCII字符表范围:
_____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 ;
根据上面的说明,这是生成的字母数字代码段:
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)); // i.e: "7GL9F0ne6t"
或者,如果您会:
const randomString = (n, r='') => {
while (n--) r += String.fromCharCode((r=Math.random()*62|0, r+=r>9?(r<36?55:61):48));
return r;
};
console.log(randomString(10))
最简单的方法是:
(new Date%9e6).toString(36)
这会根据当前时间生成5个字符的随机字符串。示例输出为4mtxj
or 4mv90
或4mwp1
问题是,如果您在同一秒钟两次调用它,它将生成相同的字符串。
比较安全的方法是:
(0|Math.random()*9e6).toString(36)
这将生成一个随机的4或5个字符的字符串,始终不同。示例输出类似于30jzm
或1r591
或4su1a
无论哪种方式,第一部分都会生成一个随机数。该.toString(36)
部分将数字转换为以base36(字母十进制)表示的形式。
(+new Date).toString(36)
(0|Math.random()*6.04e7).toString(36)
来覆盖它。
(Math.random()*1e20).toString(36)
。
这是一些简单的衬板。更改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"]();});
我知道每个人都已经做好了,但是我想尽可能以最轻便的方式(轻巧的代码而不是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 || ''
;
current || (current = '');
如果有人对一次性分配内存的单行(尽管不是为了格式化方便)感兴趣(但请注意,对于小字符串来说,这确实没有关系),这是如何做的:
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)
。
这是我创建的方法。
它将创建一个包含大写和小写字符的字符串。
另外,我还包含了将创建字母数字字符串的函数。
工作示例:
http : //jsfiddle.net/greatbigmassive/vhsxs/ (仅限字母)
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)));
}
假设您使用underscorejs,则可以仅在两行中优雅地生成随机字符串:
var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var random = _.sample(possible, 5).join('');
const c = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
const s = [...Array(5)].map(_ => c[~~(Math.random()*c.length)]).join('')
快速改进的算法。不保证统一(见评论)。
function getRandomId(length) {
if (!length) {
return '';
}
const possible =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
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);
}
}
let result = '';
for (let i = 0; i < length; i++) {
result += possible.charAt(array[i] % 62);
}
return result;
}
crypto.getRandomValues
返回256个唯一值之一。因为256不除以62,所以最终得到字符AH的可能性会稍高。我认为最好的解决方案是做YouTube所做的事情,然后在字符集中添加2个其他字符(可能是-
和_
)。无论如何,出色的工作-这个答案需要更多的爱:)
回答“我需要随机字符串”问题(无论使用哪种语言)的问题实际上是每个解决方案都使用有缺陷的字符串长度基本规范。问题本身很少揭示为什么需要随机字符串,但是我会挑战您很少需要长度随机的字符串(例如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”
请注意,由于使用的字符集中的字符总数不同,字符串长度也有所不同。在指定数量的潜在字符串中重复的风险是相同的。字符串长度不是。最重要的是,重复的风险和潜在的字符串数是明确的。不再需要猜测字符串的长度。
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 - 1
:-/
--strLength
到strLength--
补丁对我来说。
一班轮:
Array(15).fill(null).map(() => Math.random().toString(36).substr(2)).join('')
// Outputs: 0h61cbpw96y83qtnunwme5lxk1i70a6o5r5lckfcyh1dl9fffydcfxddd69ada9tu9jvqdx864xj1ul3wtfztmh2oz2vs3mv6ej0fe58ho1cftkjcuyl2lfkmxlwua83ibotxqc4guyuvrvtf60naob26t6swzpil
Array(15)
为较小的值。例如:Array(4)
。
这肯定可以工作
<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>
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));
此功能的好处是您可以获取不同长度的随机字符串,并且可以确保字符串的长度。
function randStr(len) {
let s = '';
while (len--) s += String.fromCodePoint(Math.floor(Math.random() * (126 - 33) + 33));
return s;
}
// usage
console.log(randStr(50));
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
var possible
在接受的答案中添加一个赞,那将很酷,因此该函数的结果更具可配置性。
生成10个字符长的字符串。长度由参数设置(默认为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;
}
您可以使用coderain。这是一个根据给定模式生成随机代码的库。使用#
作为大小写字母以及数字的占位符:
var cr = new CodeRain("#####");
console.log(cr.next());
还有其他占位符,例如A
大写字母或9
数字。
可能有用的是 .next()
将始终为您带来独特的结果,因此您不必担心重复。
这是一个演示应用程序,它生成唯一的随机代码列表。
全面披露:我是coderain的作者。
true-random
!他们只是pseudo-random
。将随机字符串用于保护或安全性时,请勿使用其中任何一个!!!尝试以下一种api:random.org