javascript-如何生成像“ aX4j9Z”这样的简短uid(在JS中)
对于我的Web应用程序(使用JavaScript),我想生成简短的指导(针对不同的对象-实际上是不同的类型-字符串和字符串数组)
我的uid(向导)需要类似“ aX4j9Z”的名称。
因此,这些uid应该足够轻巧,可以进行Web传输和js字符串处理,并且对于不大的结构(不超过10k个元素)来说应该是非常独特的。 说“非常独特”是指在生成uid之后,我可以检查该uid是否已经存在于结构中,如果存在则重新生成。
有关预打包的解决方案(Math.random
软件包),请参见@Mohamed的答案。 如果您没有特殊要求,则最好不要使用此页面上的任何其他解决方案。
一个6个字符的字母数字序列足以随机索引10k集合(366 = 22亿,363 = 46656)。
function generateUID() {
// I generate the UID from two parts here
// to ensure the random number provide enough bits.
var firstPart = (Math.random() * 46656) | 0;
var secondPart = (Math.random() * 46656) | 0;
firstPart = ("000" + firstPart.toString(36)).slice(-3);
secondPart = ("000" + secondPart.toString(36)).slice(-3);
return firstPart + secondPart;
}
随机生成的UID在生成〜√N个数字后会发生冲突(生日悖论),因此需要6位数字才能安全生成而不进行检查(旧版本仅生成4位数字,如果不进行检查,则在1300个ID后会有冲突) 。
如果进行冲突检查,位数可以减少3或4,但是请注意,当您生成越来越多的UID时,性能将线性降低。
var _generatedUIDs = {};
function generateUIDWithCollisionChecking() {
while (true) {
var uid = ("0000" + ((Math.random() * Math.pow(36, 4)) | 0).toString(36)).slice(-4);
if (!_generatedUIDs.hasOwnProperty(uid)) {
_generatedUIDs[uid] = true;
return uid;
}
}
}
如果您需要唯一性而不是不可预测性,请考虑使用顺序生成器(例如Math.random
、user134_item2
等)。 您可以“哈希”顺序生成的字符串以恢复不可预测性。
使用Math.random
生成的UID是不安全的(无论如何,您都不应该信任客户端)。 不要在任务关键型任务中依赖其唯一性或不可预测性。
还有一个可怕的npm软件包:shortid
简短的非顺序url友好型唯一ID生成器。
ShortId创建令人惊讶的短非连续url友好的唯一ID。 非常适合网址缩短器,MongoDB和Redis ID,以及其他用户可能会看到的ID。
- 默认情况下,包含7-14个网址友好字符:A-Z,a-z,0-9,_-
- 非顺序的,因此它们是不可预测的。
- 支持群集(自动),自定义种子,自定义字母。
- 可以生成任意数量的ID(无重复),甚至每天数百万。
- 非常适合游戏,特别是如果您担心作弊,因此您不希望有容易猜到的ID。
- 应用程序可以重新启动任何次数,而无需重复ID。
- Mongo ID / Mongoose ID的流行替代品。
- 可在Node,io.js和Web浏览器中使用。
- 包括摩卡咖啡测试。
用法
var shortid = require('shortid');
console.log(shortid.generate()); //PPBqWA9
如果区分大小写并且所有位置均允许数字,则以下代码将生成3个字符的62 ^ 3(238,328)个唯一值。 如果不要求区分大小写,请从字符字符串中删除大写或小写字符,它将生成35 ^ 3(42,875)个唯一值。
可以很容易地进行修改,以便第一个字符始终是一个字母或所有字母。
毫无疑问,可以对其进行优化,并且在达到限制时也可以拒绝返回ID。
var nextId = (function() {
var nextIndex = [0,0,0];
var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
var num = chars.length;
return function() {
var a = nextIndex[0];
var b = nextIndex[1];
var c = nextIndex[2];
var id = chars[a] + chars[b] + chars[c];
a = ++a % num;
if (!a) {
b = ++b % num;
if (!b) {
c = ++c % num;
}
}
nextIndex = [a, b, c];
return id;
}
}());
这将生成一系列唯一值。 当所有值都用尽时,它可以通过增加字符串长度来改善RobG的答案。
var IdGenerator = (function () {
var defaultCharset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890!@#$%^&*()_-+=[]{};:?/.>,<|".split("");
var IdGenerator = function IdGenerator(charset) {
this._charset = (typeof charset === "undefined") ? defaultCharset : charset;
this.reset();
};
IdGenerator.prototype._str = function () {
var str = "",
perm = this._perm,
chars = this._charset,
len = perm.length,
i;
for (i = 0; i < len; i++) {
str += chars[perm[i]];
}
return str;
};
IdGenerator.prototype._inc = function () {
var perm = this._perm,
max = this._charset.length - 1,
i;
for (i = 0; true; i++) {
if (i > perm.length - 1) {
perm.push(0);
return;
} else {
perm[i]++;
if (perm[i] > max) {
perm[i] = 0;
} else {
return;
}
}
}
};
IdGenerator.prototype.reset = function () {
this._perm = [];
};
IdGenerator.prototype.current = function () {
return this._str();
};
IdGenerator.prototype.next = function () {
this._inc();
return this._str();
};
return IdGenerator;
}).call(null);
用法:
var g = new IdGenerator(),
i;
for (i = 0; i < 100; i++) {
console.log(g.next());
}
要点包含上述实现和递归版本。
var letters = 'abcdefghijklmnopqrstuvwxyz';
var numbers = '1234567890';
var charset = letters + letters.toUpperCase() + numbers;
function randomElement(array) {
with (Math)
return array[floor(random()*array.length)];
}
function randomString(length) {
var R = '';
for(var i=0; i<length; i++)
R += randomElement(charset);
return R;
}
您可以将GUID缩短为20个可打印ASCII字符,而不会丢失信息或GUID的唯一性。
Jeff Atwood在几年前写了博客:
装备我们的ASCII装甲
只是随机生成一些字符串:
function getUID(len){
var chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
out = '';
for(var i=0, clen=chars.length; i<len; i++){
out += chars.substr(0|Math.random() * clen, 1);
}
// ensure that the uid is unique for this page
return getUID.uids[out] ? getUID(len) : (getUID.uids[out] = out);
}
getUID.uids = {};