如何在 Ruby 中生成唯一的六位字母数字代码

Posted

技术标签:

【中文标题】如何在 Ruby 中生成唯一的六位字母数字代码【英文标题】:How to generate unique six digit alpha-numeric code in Ruby 【发布时间】:2011-08-20 02:13:17 【问题描述】:

我需要生成一个唯一的六位字母数字代码。在我的数据库中保存为凭证编号:每笔交易。

【问题讨论】:

为什么不简单地自动递增代码?那时他们将是数字。如果您的代码太多(超过 6 位),您可以使用此数字的 Base32 编码,例如 可能重复? ***.com/questions/88311/… @Teoulas 我不这么认为。这个问题中没有任何内容表明代码必须是(或出现)随机的。 【参考方案1】:

更好的方法是让数据库处理 ids(递增)。但是如果你坚持自己生成它们,你可以使用随机生成器来生成代码,检查它与 db 的唯一性。然后要么接受要么重新生成

【讨论】:

这在理论上是个坏主意,因为你开始填满可用的命名空间,因为你的冲突机会增加了,在极端情况下,你可能会陷入很长时间的再生循环在您找到免费密钥之前。【参考方案2】:

我会使用数据库来生成唯一的密钥,但如果你坚持这样做:

class AlnumKey

  def initialize
    @chars = ('0' .. '9').to_a + ('a' .. 'z').to_a
  end

  def to_int(key)
    i = 0
    key.each_char do |ch|
      i = i * @chars.length + @chars.index(ch)
    end
    i
  end

  def to_key(i)
    s = ""
    while i > 0 
      s += @chars[i % @chars.length]
      i /= @chars.length
    end
    s.reverse 
  end

  def next_key(last_key)
    to_key(to_int(last_key) + 1) 
  end
end

al = AlnumKey.new
puts al.next_key("ab")
puts al.next_key("1")
puts al.next_key("zz")

当然,您必须将当前密钥存储在某个地方,这绝不是线程/多会话安全等。

【讨论】:

【参考方案3】:

我用过这个

  require 'sha1'
  srand
  seed = "--#rand(10000)--#Time.now--"
  Digest::SHA1.hexdigest(seed)[0,6]

How to generate a random string in Ruby这个链接很有用

【讨论】:

这是一个非常糟糕的答案,很容易发生冲突。在 100 万次迭代中,在 215000 个键上有 767000 次碰撞。将随机数从10000 碰撞到10000000 将碰撞减少到“仅”31,000 次(1,000,000 次),但任何碰撞仍然很糟糕。无论 Time.now 始终相同还是每次调用都返回一个新值(例如每秒不超过一个事务),都是如此。 在正常情况下这是可以接受的。有没有其他办法。【参考方案4】:

有以下限制:

    仅在 2038-12-24 00:40:35 UTC 之前有效 在一秒钟内生成不超过一次

你可以使用这个简单的代码:

Time.now.to_i.to_s(36)
# => "lks3bn"

【讨论】:

如果系统时间改变会怎样? 一次我需要获取不同的凭证 ID @Zabba 这会导致问题,但我认为它不会那么频繁。在这种情况下,系统将不得不停机维护,时间跨度等于新旧时区之间的差异。最坏的情况是不到一天。如果新时区提前,系统不必关闭。【参考方案5】:
class IDSequence
  attr_reader :current
  def initialize(start=0,digits=6,base=36)
    @id, @chars, @base = start, digits, base
  end
  def next
    s = (@id+=1).to_s(@base)
    @current = "0"*(@chars-s.length) << s
  end
end

id = IDSequence.new
1234.times id.next 

puts id.current
#=> 0000ya

puts id.next
#=> 0000yb

9876543.times id.next 
puts id.current
#=> 05vpqq

【讨论】:

【参考方案6】:

这将通过获得毫秒来缓解时间冲突问题

(Time.now.to_f*1000.0).to_i

【讨论】:

以上是关于如何在 Ruby 中生成唯一的六位字母数字代码的主要内容,如果未能解决你的问题,请参考以下文章

在django中生成唯一的字母数字标识符[重复]

java读取excel, excel中有一列是特殊格式-邮政编码,是0开头的六位数字,读取上来,转化成string,

如何在 Python 中生成唯一 ID? [复制]

ruby - 如何从字符串数组中生成可能的字母顺序组合?

在 Oracle PL/SQL 中生成字母数字序列

在Java中生成字母数字随机字符串[重复]