生成唯一的ids js

generate unique ids js

本文关键字:ids js 唯一      更新时间:2023-09-26

在Jasmine中运行一些测试,试图让这些代码发挥作用,发现id不是唯一的。这是有道理的,因为它们是这样随机生成的。

var Robot = function(){
    this.name = makeid();
    function makeid()
    {
        var text = "";
        var possible ="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        for( var i=0; i < 2; i++ ){
            text += possible.charAt(Math.floor(Math.random() * possible.length));
        }
        var possibleNums ="0123456789";
        for( var j=0; j < 3; j++ ){
            text += possibleNums.charAt(Math.floor(Math.random() * possibleNums.length));
        }
        return text;
    }
};

我需要它来完成这个测试。

it('there can be lots of robots with different names each', function() {
    var i,
        numRobots = 10000,
        usedNames = {};
    for (i = 0; i < numRobots; i++) {
      var newRobot = new Robot();
      usedNames[newRobot.name] = true;
    }
    expect(Object.keys(usedNames).length).toEqual(numRobots);
  });

我的理论是,我可以制作一个数组,将每个名称推到它上面,然后比较其唯一性。这看起来可能令人沮丧。我想知道是否还有其他方法,也许可以保证生成时的唯一性,或者一些不涉及数组的简单比较工具。

编辑:日期戳方法是确保唯一id的好方法,但不幸的是,我不得不使用我用来通过另一个测试的id生成方法。本质上,我需要id是5个字符,后面跟着2个大写字母和3个数字。

您可以使用Date.now(),而不是使用自定义的唯一ID生成系统,它以毫秒为单位返回日期和时间,如下所示:1463004819469

Date.now()每毫秒变化一次,而且总是不稳定的。假设你的程序没有多个线程,事情必须按顺序进行,所以不会有两个相同的ID。

例如:

var Robot = function(){
    this.name = Date.now(); //1463004819469
}

希望这能解决你的问题!


编辑:如果连续调用new Robot()两次,则可能会得到相同的ID。您可以将Date.now()连接到自定义的唯一ID或随机数,例如

  • this.name = String(Date.now())+Math.floor(Math.random()*10000);
  • this.name = String(Date.now())+makeid();
  • this.name = String(Date.now())+String(counter); //increment this every time you create a Robot

这些只是示例,您可以创建任何想要的组合。

老实说,你为什么不直接用柜台呢?像这样:

var counter = 0;
var Robot = function(){
    counter++;
    this.name = counter;
}

除非ID也存在于程序之外,否则在这种情况下,这是行不通的。

我知道这个问题更具体,但也许像我这样的人只是在寻找获取ID的捷径gist.github.com/gordonbrander/230317 by gordonbrander/ID.js

  var ID = function () {
  // Math.random should be unique because of its seeding algorithm.
  // Convert it to base 36 (numbers + letters), and grab the first 9 characters
  // after the decimal.
  return '_' + Math.random().toString(36).substr(2, 9);
};

稍微修改一下你的代码,你就可以得到保证的唯一id,但我不建议像100000多个这样的机器人大军这样做,因为它会非常慢。

var Robot = function(){
    this.name = this.makeId();
};
Robot.prototype.makeId = function makeId(){
  var     text = "",
      possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
  possibleNums = "0123456789";
  for( var i=0; i < 2; i++ ){
    text += possible.charAt(Math.floor(Math.random() * possible.length));
  }
  for( var j=0; j < 3; j++ ){
    text += possibleNums.charAt(Math.floor(Math.random() * 10));
  }
return !~Robot.prototype.ids.indexOf(text) ? (Robot.prototype.ids.push(text),text) : makeId();
};
Robot.prototype.ids = [];
function robotFactory(n){
  a = [];
  for(var i = 0; i < n; i++) a.push(new Robot());
  return a;
}
var myRobotArmy = robotFactory (10000);

编辑@2017年8月18日

检查上面的代码,我认为我本可以做得更好。尤其是在indexOf部分,这是一个巨大的性能瓶颈。现在它跑得快多了。此外,我本可以通过将实例化对象设为私有对象来隐藏不必要的数据和功能,从而更好地构建构造函数。另一件事是所需的命名方案只允许676000个名称(26 x 26 x 10 x 10),因此要求更多的机器人将导致堆栈溢出,因为我们将拥有所有可能的名称,但仍在尝试生成唯一的名称。当然,这可以通过从一开始就限制军队规模来防止。但是,考虑一下要求拥有一支由676000个机器人组成的军队。随机名称生成器的失败率将随着所用名称在哈希表中的堆积而增加。根据姓氏,我们将不得不尝试数十万个随机名字,直到我们得到最后一个唯一的名字。在这种特殊情况下,您有两种解决方案;

1) 如果你想要1M规模的机器人,那么至少以XYZ123的形式命名2) 如果您将使用大多数可用的命名方案,如XY123,并且您想要600K个机器人,则不是随机分配名称,而是按顺序分配名称。

function Robot(){
 this.name = Robot.makeId();
}
Robot.nums   = Array.from({length:10},(_,i) => i);
Robot.chars  = Array.from({length:26},(_,i) => String.fromCharCode(65+i));
Robot.idmap  = {};
Robot.makeId = function(){
                 var text = Array.from({length:2}, _ => Robot.chars[~~(Math.random()*26)]).join("") +
                            Array.from({length:3}, _ => Robot.nums[~~(Math.random()*10)]).join("");
                 return !Robot.idmap[text] ? (Robot.idmap[text] = true,text) : Robot.makeId();
               };
function robotFactory(n){
  a = [];
  for(var i = 0; i < n; i++) a.push(new Robot());
  return a;
}
var myRobotArmy = robotFactory(10);
console.log(myRobotArmy);

如果你只想要一个对你自己的页面唯一的id,你只需要一个计数器就可以做到这一点:

var unique = (function() {
    var cntr = 0;
    return function(prefix) {
        prefix = prefix || "";
        return prefix + cntr++;
    }
})();
console.log(unique("myid"));   // "myid0"
console.log(unique("myid"));   // "myid1"

在你的代码中使用它:

var unique = (function() {
    var cntr = 0;
    return function(prefix) {
        prefix = prefix || "";
        return prefix + cntr++;
    }
})();
var Robot = function(){
    this.name = unique("robot");
};

单调递增计数器是确保在此范围内生成唯一名称所需的全部计数器。


如果你想生成在所有客户端中极有可能是唯一的字符串,你可以使用下面的答案:

唯一随机DIV ID

唯一随机数组javascript

在不同的输入文本上生成随机数,并确保显示的随机数是唯一的

如果你想在世界上的所有页面/用户中获得完全的保证,那么你必须使用中央服务器来协调和分配唯一的值,或者使用一些已知的唯一客户端种子(PC上的GUID生成器通常使用以太网mac地址作为种子,因为其他计算机不会重复这些操作)。

这是我在JS代码中使用的函数:

function uniqueid() {
    // always start with a letter (for DOM friendlyness)
    var idstr = String.fromCharCode(Math.floor((Math.random() * 25) + 65));
    do {
        // between numbers and characters (48 is 0 and 90 is Z (42-48 = 90)
        var ascicode = Math.floor((Math.random() * 42) + 48);
        if (ascicode < 58 || ascicode > 64) {
            // exclude all chars between : (58) and @ (64)
            idstr += String.fromCharCode(ascicode);
        }
    } while (idstr.length < 32);
    return (idstr);
}