【问题标题】:Sequenced string PK's in pythonpython中的序列化字符串PK
【发布时间】:2013-12-27 12:48:59
【问题描述】:

我正在寻找可用作用户 ID 生成器的最佳字符串序列生成器。据我所知,它应该实现以下功能:

  • 长度限制为 8 个字符。
  • 由拉丁符号和数字组成
  • 公开,因此应该被混淆

现在我想出了以下算法:

def idgen(begin, end):
    assert type(begin) is int
    assert type(end) is int
    allowed = reduce(
        lambda L, ri: L + map(chr, range(ord(ri[0]), ord(ri[1]) + 1)),
        (('a', 'z'), ('0', '9')), list()
    )
    shift = lambda c, i: allowed[(allowed.index(c) + i) % len(allowed)]
    for cur in xrange(begin, end):
        cur = str(cur).zfill(8)
        cur = izip(xrange(0, len(cur)), iter(cur))
        cur = ''.join([shift(c, i) for i, c in cur])
        yield cur

但它会给出非常相似的 id,例如 0-100: '01234567'、'01234568'、'01234569'、'0123456a'等

那么最佳实践是什么?怎么样,我想 url 缩短器应该使用某种类似的算法?

【问题讨论】:

标签: python string algorithm sequences


【解决方案1】:

由于您需要“混淆”的 id,因此您需要 看起来 随机但并非如此的东西。幸运的是,几乎所有计算机生成的随机性fulfills this criteria,包括由random python 模块生成的随机性。

您可以通过设置 PRNG 种子来生成固定的数字序列,如下所示:

import random
import string

valid_characters= string.lowercase+string.digits

def get_random_id():
    return ''.join(random.choice(valid_characters) for x in range(8))

random.seed(0)
for x in range(10):
    print get_random_id()

这将始终打印相同的 10 个“随机”ID 序列。

您可能希望按需生成 id,而不是一次性生成。为此,您需要保持 PRNG 状态:

random.setstate( get_persisted() )
get_random_id()
persist( random.getstate )
#repeat ad infinitum

这有点昂贵,因此您需要一次生成几个随机 ID,并将它们放在队列中。您也可以使用random.jumpahead,但我建议您尝试两种技术,看看哪一种更快。

避免此任务的冲突并非易事。即使使用散列函数也不能使您免于冲突。

random 模块的 PRNG has a period of 2**19937-1。你至少需要一个(26+10)**8的句号,大约是2**42。但是,您需要的周期低于 PRNG 的周期这一事实并不能保证不会发生冲突,因为您的输出大小(8 字节或 64 位)可能与 PRNG 的输出大小不匹配.此外,根据 choice 的特定实现,即使大小匹配,PRNG 也有可能在每次调用时简单地推进 PRNG。

可以尝试遍历键空间,检查是否有重复:

random.seed(0)
space=len(valid_characters)**8
found=set()
x=0
while x<space:
    id= get_random_id()
    if id in found:
        print "cycle found after",x,"iterations"
    found.update(id)
    if not x% 1000000:
        print "progress:",(float(x)/space)*100,"%"
    x+=1

但这需要很长时间,很长

您也可以手工制作具有所需周期的 PRNG,但它有点超出了 stackoverflow 的范围。你可以试试the math stackexchange

最终,根据您的目的,我认为您最好的选择可能只是跟踪已生成的 ID,并跳过重复的 ID

【讨论】:

  • 很好的答案,谢谢。我对随机有点直截了当,忘记了 sid 功能。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-16
  • 2020-09-13
  • 1970-01-01
  • 2021-04-14
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多