Javascript 如何生成像“aX4j9Z”这样的短 uid(在 JS 中)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6248666/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 20:55:51  来源:igfitidea点击:

How to generate short uid like "aX4j9Z" (in JS)

javascripthashguid

提问by WHITECOLOR

For my web application (in JavaScript) I want to generate short guids (for different objects - that are actually different types - strings and arrays of strings)

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

I want something like "aX4j9Z" for my uids (guids).

我想要像“aX4j9Z”这样的东西作为我的 uids(guids)。

So these uids should be lightweight enough for web transfer and js string processing and quite unique for not a huge structure (not more than 10k elements). By saying "quite unique" I mean that after the generation of the uid I could check whether this uid does already exist in the structure and regenerate it if it does.

因此,这些 uid 应该足够轻量级以进行 web 传输和 js 字符串处理,并且对于不是一个巨大的结构(不超过 10k 个元素)来说非常独特。说“非常独特”是指在生成 uid 之后,我可以检查该 uid 是否已经存在于结构中,如果存在则重新生成它。

回答by kennytm

See @Mohamed's answerfor a pre-packaged solution (the shortidpackage). Prefer that instead of any other solutions on this page if you don't have special requirements.

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



A 6-character alphanumeric sequence is pretty enough to randomly index a 10k collection (366= 2.2 billion and 363= 46656).

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

UIDs generated randomly will have collision after generating ~ √N numbers (birthday paradox), thus 6 digits are needed for safe generation without checking (the old version only generates 4 digits which would have a collision after 1300 IDs if you don't check).

随机生成的UID在生成~√N个数字后会发生冲突(生日悖论),因此需要6位数字才能安全生成,无需检查(旧版本仅生成4位数字,如果不检查1300个ID后会发生冲突) .

If you do collision checking, the number of digits can be reduced 3 or 4, but note that the performance will reduce linearly when you generate more and more UIDs.

如果做碰撞检查,位数可以减少 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;
        }
    }
}

Consider using a sequential generator (e.g. user134_item1, user134_item2, …) if you require uniqueness and not unpredictability. You could "Hash" the sequentially generated string to recover unpredictability.

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

UIDs generated using Math.randomis not secure (and you shouldn't trust the client anyway). Do notrely on its uniqueness or unpredictability in mission critical tasks.

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

回答by Mohamed Ramrami

There is also an awsome npm package for this : shortid

还有一个很棒的npm 包:shortid

Amazingly short non-sequential url-friendly unique id generator.

ShortId creates amazingly short non-sequential url-friendly unique ids. Perfect for url shorteners, MongoDB and Redis ids, and any other id users might see.

  • By default 7-14 url-friendly characters: A-Z, a-z, 0-9, _-
  • Non-sequential so they are not predictable.
  • Supports cluster (automatically), custom seeds, custom alphabet.
  • Can generate any number of ids without duplicates, even millions per day.
  • Perfect for games, especially if you are concerned about cheating so you don't want an easily guessable id.
  • Apps can be restarted any number of times without any chance of repeating an id.
  • Popular replacement for Mongo ID/Mongoose ID.
  • Works in Node, io.js, and web browsers.
  • Includes Mocha tests.

非常短的非顺序 url 友好的唯一 id 生成器。

ShortId 创建了非常短的非顺序 url 友好的唯一 id。非常适合 url 缩短器、MongoDB 和 Redis id,以及用户可能看到的任何其他 id。

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

Usage

用法

var shortid = require('shortid');
console.log(shortid.generate()); //PPBqWA9

回答by RobG

The following generates 62^3 (238,328) unique values of 3 characters provided case sensitivity is unique and digits are allowed in all positions. If case insensitivity is required, remove either upper or lower case characters from chars string and it will generate 35^3 (42,875) unique values.

如果区分大小写是唯一的并且所有位置都允许数字,则以下生成 3 个字符的 62^3 (238,328) 个唯一值。如果需要不区分大小写,请从 chars 字符串中删除大写或小写字符,它将生成 35^3 (42,875) 个唯一值。

Can be easily adapted so that first char is always a letter, or all letters.

可以很容易地进行调整,以便第一个字符始终是一个字母,或所有字母。

No dobut it can be optimised, and could also refuse to return an id when the limit is reached.

毫无疑问,它可以优化,也可以在达到限制时拒绝返回 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;
  }
}());

回答by ninjagecko

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

回答by Ilia Choly

This will generate a sequence of unique values. It improves on RobG's answer by growing the string length when all values have been exhaused.

这将生成一系列唯一值。当所有值都用完时,它通过增加字符串长度来改进 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);

Usage:

用法:

var g = new IdGenerator(),
    i;

for (i = 0; i < 100; i++) {
   console.log(g.next());
}

This gistcontains the above implementation and a recursive version.

该要点包含上述实现和递归版本。

回答by Martin Braun

Here is a one liner, but it gives only lowercase letters and numbers:

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

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

console.log(uuid);

回答by Christian Specht

You can shorten a GUID to 20 printable ASCII characters without losing information or the uniqueness of the GUID.

您可以将 GUID 缩短为 20 个可打印的 ASCII 字符,而不会丢失信息或 GUID 的唯一性。

Jeff Atwood blogged about that years ago:
Equipping our ASCII Armor

杰夫·阿特伍德 (Jeff Atwood) 多年前在博客中写道:
装备我们的 ASCII 装甲

回答by Prathamesh More

You can use the md5 algorithm for generating a random string. md5 is the node package

您可以使用 md5 算法生成随机字符串。md5 是节点包

 var randomChars = Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 2);
 var shortUrl = md5(originalUrl + randomChars + new Date()).substring(0, 5).toString();
 console.log(shortUrl);

This will generate unique string every time.

这将每次生成唯一的字符串。

回答by Mark Kahn

just randomly generate some strings:

只是随机生成一些字符串:

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