我如何找到下一个ID?

时间:2014-10-17 17:44:27

标签: javascript algorithm design-patterns

我正在尝试找出在Javascript应用程序中实现nextId()的最佳方法,该应用程序为其对象发布唯一ID。如果重要的话,这是一个我正在做的程序,作为纯JS,HTML和CSS(没有库,框架,DBMS等)的学习体验。我在这里看到了一个类似的问题(虽然我无法再找到它的链接),答案不仅包括存储与布尔值配对的可能ID列表以确定是否使用了id,还将已删除的ID存储在回收列表中,以用于将来需要它的对象。我认为后一种选择听起来更好,但我确信还有更多的方法可以做到这一点。有谁知道这项任务是否有模式,算法或其他最佳实践?

编辑: 我希望允许用户在应用程序生命周期的某个时刻共享数据,因此已存在的ID可能会在某些时候成为问题。我希望这些ID是永久性的,因为我将使用LocalStorage保存数据。一个简单的整数将起作用,我将用一两个字母前缀来标识对象的类型。填补空洞也很好,所以当用户长期使用它时,整数不会太高(一厢情愿)。

此外,所有对象都是在程序开头用字符串构造的(我知道它很疯狂)。

6 个答案:

答案 0 :(得分:1)

如果你只需要一个页面生命周期唯一的id,你可以在页面中使用一个简单的单调增加计数器:

var getUniqueID = (function() {
    var cntr = 0;
    return function() {
        return cntr++;
    };
})();

var idA = getUniqueID();
var idB = getUniqueID();

确保您的ID在所有用户中都是唯一的,这是一项更高的任务。如果不涉及为您输入唯一ID的中央服务器,这里的一般概念是创建一个由三件事组合而成的id:

  1. 用户唯一的令牌(如userID)
  2. 保证会话唯一的令牌(就像我们上面所说的那样)
  3. 随机值。
  4. 如果做得好,两个不同用户之间永远不会发生冲突(因为userID在id中)并且计数器使得没有用户在同一个会话中两次生成相同的id并且随机值产生赔率在相同的会话中自己生成相同id的用户非常小。

    var getGUID = (function() {
        var cntr = 0;
        return function(userID) {
            var rand = Math.random().toString().replace(".", "");
            return userID + "_" + rand + "_" + cntr++;
        };
    })();
    
    var idA = getGUID(myUserID);
    var idB = getGUID(myUserID);
    

    注意:这是GUID生成的更简单方法,假设您已经拥有userID。关于生成GUID的各种策略有很多研究和文献,如果你想要超出这个范围的话,你当然可以阅读更多。关于该主题的一些参考文献:

    http://en.wikipedia.org/wiki/Globally_unique_identifier
    
    http://betterexplained.com/articles/the-quick-guide-to-guids/
    
    http://www.uddi.org/pubs/draft-leach-uuids-guids-01.txt
    

答案 1 :(得分:0)

根据用例,我想创建一个复杂的唯一ID:

function newGUID(){

        var result = '';
        var hexcodes = "0123456789abcdef".split("");

        for (var index = 0; index < 32; index++) {
            var value = Math.floor(Math.random() * 16);

            switch (index) {
                case 8:
                    result += '-';
                    break;
                case 12:
                    value = 4;
                    break;

            }
            result += hexcodes[value];
        }
        return result;
    }

答案 2 :(得分:0)

您可以将UUID用作ID。 There's one answer here in SO where you can generate UUIDs in JS。 UUID通常足以用作ID。只是为了确保id不是一个骗局,你可以拥有一个对象,其键是使用过的ID。生成ID时,您可以通过在对象中添加ID来跟踪它们。然后,您可以通过执行obj.hasOwnProperty(id)来查找它们。

你可以这样做

var idStorage = {};
var id;

// generate ID that's unique and hasn't been used
do{
  id = guid();
} while (idStorage.hasOwnProperty(id));

idStorage[id] = true;

// ID is usable

此外,ID应该是唯一的。它们永远不应该重复使用。

答案 3 :(得分:0)

AngularJS有一种非常简单的方法来生成唯一ID:只需增加一个全局计数器。来自src/Angular.js

var uid = 0;

// ...

/**
 * A consistent way of creating unique IDs in angular.
 *
 * Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before
 * we hit number precision issues in JavaScript.
 *
 * Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M
 *
 * @returns {number} an unique alpha-numeric string
 */
function nextUid() {
    return ++uid;
}

当然,您应该选择一个解决方案,具体取决于生成的ID应该是唯一的时间范围。上述解决方案将生成对于一个网页的一个会话唯一的ID。对于一个简单的单页面应用程序(Angular的用例),这样做会很好。如果您需要它们在多个页面加载中是唯一的,或者对于同一个用户是唯一的,那么您需要将uid保持更长时间(在cookie或数据库中)。如果他们需要在较长时间内保持唯一,您可能还需要查看长度超过2^53的ID。

答案 4 :(得分:0)

我会使用UUID v4,因为这些ID在任何情况下都是唯一的(没有额外的逻辑可以检查这些ID是否正在使用或者用于修复旧ID),只需在需要时发出新ID

JS中非常简单的实现如下:

function generateUUID(){
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
        return v.toString(16);
    });
}

$(function() {
  $('button').bind('click', function() {
     $('input').val(generateUUID());
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" style="width: 350px;"/><button>GENERATE NEW ID</button>

答案 5 :(得分:0)

嗯,它有点不清楚你对这些ID的期望,但是如果你只想在你的系统中每种类型的实体都有一个唯一的id而你的数据只能存在于内存中,那么你可以使用以下方法:

注意:我从评论中看到你想要一个代表实体的前缀。

function identitySequence(base) {
    var id = base || 0;

    return function () {
        return ++id;
    };
}

//Lets say you had some sort of repository for every entity
function InMemoryUserRepository(nextId) {
    this._nextId = nextId;
}

InMemoryUserRepository.prototype = {
    constructor: InMemoryUserRepository,

    get nextId() { return 'user-' + this._nextId(); }

    //other operations, like save...
};


var userRepository = new InMemoryUserRepository(identitySequence());

userRepository.nextId; //user-1

现在,假设您希望您的ID序列在localStorage中保持不变,您可以执行以下操作(扩展上述代码):

var userRepository = new InMemoryUserRepository(localStorageIdentitySequence('userIdSeq'));

userRepository.nextId; //user-1

//Reload page

userRepository.nextId; //user-2


function localStorageIdentitySequence(storageKey) {
    var next = identitySequence(+localStorage.getItem(storageKey));

    return function () {
        return +(localStorage[storageKey] = next());
    };
}

这适用于单台计算机,但是如果您想要一个可以跨机器生成唯一ID的唯一ID生成器,那么这种方法将无效。您必须从可以被所有客户端访问的服务器生成ID,或者您可以在客户端上生成GUID。无法知道GUID是否已由其他客户端生成,但这种可能性很小。