如何生成短的uid,如"aX4j9Z"(在JS中)

WHI*_*LOR 57 javascript hash guid

对于我的Web应用程序(在JavaScript中)我想生成短指针(对于不同的对象 - 实际上是不同的类型 - 字符串和字符串数组)

我想为我的uids(guids)提供类似"aX4j9Z"的东西.

因此,这些uid应该足够轻量级,以便进行Web传输和js字符串处理,并且对于非庞大的结构(不超过10k元素)而言非常独特.通过说"非常独特",我的意思是在生成uid之后,我可以检查这个uid是否已经存在于结构中并且如果它已经存在则重新生成它.

ken*_*ytm 107

有关预先打包的解决方案(),请参阅@ Mohamed的答案.如果您没有特殊要求,请选择此页面上的任何其他解决方案.shortid


一个6个字符的字母数字序列足以随机索引10k集合(36 6 = 22亿和36 3 = 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;
}
Run Code Online (Sandbox Code Playgroud)

生成〜√N数字(生日悖论)后随机生成的UID会发生冲突,因此安全生成需要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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您需要唯一性而不是不可预测性,请考虑使用顺序生成器(例如user134_item1,user134_item2......).您可以"散列"顺序生成的字符串以恢复不可预测性.

使用生成的UID Math.random不安全(无论如何您都不应该信任客户端).难道不是依靠其在关键任务工作的独特性或不可预测性.

  • @Kranu - 它产生随机数"0"或".000000000001"的可能性很小,最后的字符串最终像"4z"."0000"确保它始终至少有4个字符 (3认同)

mod*_*diX 17

这是一个单行,但它只提供小写字母和数字:

var uuid = Math.random().toString(36).slice(-6);

console.log(uuid);
Run Code Online (Sandbox Code Playgroud)

  • 可以输入 `Date.now()` 来获取具有某种含义的序列: `Math.floor(Date.now() / 1000).toString(36);` (3认同)

Moh*_*ami 16

还有一个很棒的 npm包:shortid

令人惊讶的简短非连续url友好的唯一id生成器.

ShortId创建了非常短的非连续url友好的独特ID.适用于网址缩短程序,MongoDB和Redis ID以及用户可能看到的任何其他ID.

  • 默认情况下,7-14个网址友好字符:AZ,az,0-9,_-
  • 非顺序,因此它们是不可预测的.
  • 支持群集(自动),自定义种子,自定义字母.
  • 可以生成任意数量的ID而无需重复,甚至每天数百万.
  • 非常适合游戏,特别是如果你担心作弊,所以你不想要一个容易猜到的id.
  • 应用程序可以重新启动任意次,而无需重复ID.
  • Mongo ID/Mongoose ID的热门替代品.
  • 适用于Node,io.js和Web浏览器.
  • 包括摩卡测试.

用法

var shortid = require('shortid');
console.log(shortid.generate()); //PPBqWA9
Run Code Online (Sandbox Code Playgroud)

  • 我也**强烈**不同意。开发人员来这里是为了*代码*答案和学习,而不是为了查看 NPM 包的下载链接,无论它们有多完美。对于我的用例,我不能使用任何包,并且必须在代码本身*内集成一个解决方案。 (5认同)
  • 我**不同意反对者的观点!** OP 想要 UID。OP 没有表达您的额外限制。对于大多数人来说,一个经过充分测试的库比重新发明轮子更好,并且是正确的解决方案。如果您有其他问题,您可以发布不同的问题或替代答案。 (4认同)
  • 非常不同意“下载可能有害的软件包”应该是编程问题的答案。 (2认同)

小智 7

获取一个简单的计数器,从 100000000 开始,将数字转换为基数 36。

(100000000).toString(36);  //1njchs

(2100000000).toString(36); //yqaadc
Run Code Online (Sandbox Code Playgroud)

您可以轻松拥有 20 亿个优雅的独特 ID,就像 YouTube 一样

  • 我发现这很有帮助;很高兴不必下载整个包或为此添加功能。我使用了自纪元以来的毫秒数:`(Math.round(Date.now())).toString(36)` (2认同)

Rob*_*obG 5

以下内容生成62 ^ 3(238,328)3个字符的唯一值,前提是区分大小写且所有位置都允许使用数字.如果需要不区分大小写,请从chars字符串中删除大写或小写字符,它将生成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;
  }
}());
Run Code Online (Sandbox Code Playgroud)


Teo*_*cci 5

考虑到 ES6 功能的实际威力,我们可以在 JavaScript 中生成哈希 ID,而无需依赖第三方库。

我使用 JavaScript 目前为我们提供的内置函数实现了一个非常简单的生成器。该实现使用了Crypto.getRandomValues()and ,Uint8Array()如下代码所示:

const hashID = size => {
  const MASK = 0x3d
  const LETTERS = 'abcdefghijklmnopqrstuvwxyz'
  const NUMBERS = '1234567890'
  const charset = `${NUMBERS}${LETTERS}${LETTERS.toUpperCase()}`.split('')

  const bytes = new Uint8Array(size)
  crypto.getRandomValues(bytes)

  return bytes.reduce((acc, byte) => `${acc}${charset[byte & MASK]}`, '')
}

console.log({id: hashID(6)})
Run Code Online (Sandbox Code Playgroud)

此实现使用这些字符:[ A-Z]、[ a-z]、[ 0-9] 总共有 62 个字符,如果我们添加_-它将完成最多 64 个字符,如下所示:

const hashID = size => {
  const MASK = 0x3d
  const LETTERS = 'abcdefghijklmnopqrstuvwxyz'
  const NUMBERS = '1234567890'
  const charset = `${NUMBERS}${LETTERS}${LETTERS.toUpperCase()}_-`.split('')

  const bytes = new Uint8Array(size)
  crypto.getRandomValues(bytes)

  return bytes.reduce((acc, byte) => `${acc}${charset[byte & MASK]}`, '')
}

console.log(`id: ${hashID(6)}`)
Run Code Online (Sandbox Code Playgroud)

笔记:

每小时生成 1000 个 ID 长度为 6 个字符的 ID,大约需要 2 天的时间才能有 1% 的概率发生至少 1 次冲突。将其实施到您的项目中时请记住这一点。