从JavaScript中已知的一组潜在ID快速创建唯一字符串ID/键的方法
假设您想要一组1到2位的十六进制数,即256个数字。只是使用一个小集合来解决这个问题,但它可以处理任何大小的字符串 因此,在这种情况下,您有一个潜在的从JavaScript中已知的一组潜在ID快速创建唯一字符串ID/键的方法,javascript,algorithm,data-structures,trie,id-generation,Javascript,Algorithm,Data Structures,Trie,Id Generation,假设您想要一组1到2位的十六进制数,即256个数字。只是使用一个小集合来解决这个问题,但它可以处理任何大小的字符串 因此,在这种情况下,您有一个潜在的N或256个数字。您将为每个新的数据记录“生成”一个新的ID。因此,它开始并随机给你af,然后1d,然后8a,等等 简单而天真的方法是,只需按顺序生成所有数字,然后洗牌,然后从集合中弹出。当您只有256个数字时,这可以正常工作。但如果你有数百万或数十亿的数字,这是不切实际的,因为你可能有很多腰围生成的ID长时间不被使用。我想避免这种情况 所以我的问
N
或256个数字。您将为每个新的数据记录“生成”一个新的ID。因此,它开始并随机给你af
,然后1d
,然后8a
,等等
简单而天真的方法是,只需按顺序生成所有数字,然后洗牌,然后从集合中弹出。当您只有256个数字时,这可以正常工作。但如果你有数百万或数十亿的数字,这是不切实际的,因为你可能有很多腰围生成的ID长时间不被使用。我想避免这种情况
所以我的问题是,创建这样一个唯一的键字符串的最快方法是什么,不需要预先生成所有的键字符串,也不需要按顺序递增1或诸如此类的值。也就是说,密钥应该看起来是随机的
我可以想象的一种方法是使用trie存储已经使用/生成的值。然后,当您要获取一个新值时,您会生成一个随机值,然后检查trie以查看它是否已被使用。虽然我不知道如何判断这有多有效,但一旦你开始用完ID,并且只剩下最后几个ID,它的性能就会非常差。您将生成大量已经生成的ID,并遍历每个ID的trie,因此速度会很慢
我想知道是否有一种更有效的方法可以做到这一点,而不必事先生成所有这些内容。此外,数据记录不会用于计算ID,因为这些记录可能非常大和复杂
也许有一种方法可以对一次随机遍历(并生成)一个trie进行排序,这样就可以生成ID,因为您最终会在trie中的一个唯一的随机位置。我不知道,也许是这样的
另外,我对散列不太精通,所以我不知道是否有好的方法可以使用它。我认为混合函数正是您想要的。它将在输入中移动位以产生相同长度的输出。它是可逆的,因此每个输入对应一个唯一的输出 由于您希望输入数据不参与id生成,因此需要一个代理id。您可以为每个记录分配一个递增id,并使用mix函数对id进行置乱 您将得到如下结果:
- 记录A=>
=>id==1
混合id==0x7ed55d16
- 记录B=>
=>id==2
混合id==0xc761c23c
- 等等
- 我认为在速度、灵活性和效率之间应该有一些折衷
一方面,伪随机生成器将为您提供均匀的密钥分布,并且生成速度相当快。但是,检查现有id会很慢。您可以使用bloom过滤器(节省内存)或尝试,但正如您在某个时候所说的,您应该增加空间
另一种选择是使用它来生成每个键(但不是随机顺序)。您需要跟踪上一次发布的代码。我不确定它的性能如何,但我的想法是使用
对象
或映射
和Math.random()
让obj={}
函数生成器域(){
设id=Math.abs(0.5-Math.random())*1000
if(obj[id]){
generateRandomId()
}否则{
obj[id]=真
}
返回id
}
console.log(generateRandomId())
console.log(generateRandomId())
console.log(generateRandomId())
console.log(generateRandomId())
我正在考虑这样的问题:
var-trie=buildTrie()
变量id1=genId(trie)
变量id2=genId(trie)
console.log(id1、id2)
函数buildTrie(){
var trie=buildNode(0)
返回trie
功能构建节点(级别){
如果(电平==7){//8位
变量节点={
可用:正确,
叶:是的
}
返回节点
}否则{
var a=构建节点(级别+1)
var b=构建节点(级别+1)
变量节点={
是的,
正确:正确,
左:a,,
右:b
}
a、 父节点=节点
b、 父节点=节点
返回节点
}
}
}
函数genId(节点){
变量字节=[]
步骤(节点,字节)
var id=parseInt(bytes.join(“”),2.toString(16)
返回id
功能步骤(节点,字节){
if(node.leaf){
node.available=false
var c=节点
var p=c父项
while(p){
如果(p.left==c){
p、 availableLeft=false
}else if(p.right==c){
p、 availableRight=false
}
如果(!p.availableLeft&!p.availableRight){
c=p
p=p.parent
}否则{
p=假
}
}
}
var randomDirection=Math.random()>=0.5
如果(随机方向){
if(node.availableLeft){
字节。推送(0)
步骤(node.left,字节)
}else if(node.availableRight){
字节数。推送(1)
步骤(node.right,字节)
}
}否则{
if(node.availableRight){
字节数。推送(1)
步骤(node.right,字节)
}else if(node.availableLeft){
字节。推送(0)
步骤(node.left,字节)
}
}
}
}
我假设您可以生成顺序ID;也就是说,您有一种可靠的方法可以准确地知道到目前为止已经生成了多少ID。然后,使用任何合理快速的加密算法对该计数进行加密就足够了
加密将以二进制数的形式进行,大多数算法的加密结果都是相同大小的,也是二进制的。如果需要,可以对结果进行base-64或十六进制编码