【问题标题】:Create unique id of fixed length only using given symbols?仅使用给定符号创建固定长度的唯一 ID?
【发布时间】:2021-03-09 17:47:58
【问题描述】:

我想看看如何在 python 中创建一组固定长度(比如长度为 12)的唯一 ID,它使用所有字母数字字符的特定子集。这里的用例是这些 ID 需要人们阅读并在打印文档中引用,因此我尽量避免使用字符 L、I、O 和数字 0、1。我当然需要能够生成根据需要新的 ID。

我在其他答案中查看了 UUID 函数,但无法找到一种方法来使用该函数来满足我的要求。我已经做了很多搜索,但如果重复,请道歉。

编辑:到目前为止,我尝试使用 UUID,如 here 所述。还有hashids 函数。但无法想出使用它们的方法。我能想出的下一个最佳解决方案是创建一个随机字符串列表,并检查所有现有的 id。但这似乎效率很低。

【问题讨论】:

  • 你能告诉我们你到目前为止所做的尝试吗?
  • 不能解决你的问题,但我相信有特殊的字体类型可以避免字符之间的混淆。这可以让你的问题更容易一些。
  • 只有两种方法可以保证唯一性。首先是让 ID 变得巨大,并包含已知唯一的元素;这就是 UUID 的工作方式。其次是拥有一个只发布唯一号码的数据库,但每个人都会被绑定到该数据库。

标签: python


【解决方案1】:

你可以使用像itertools.combinations这样的迭代器

import itertools
import string

valid_chars = set(string.ascii_lowercase + string.digits) - set('lio01')

# Probably would want to persist the used values by using some sort of database/file
# instead of this
used = set()

unique_id_generator = itertools.combinations(valid_chars, 12)

generated = "".join(next(unique_id_generator))
while generated in used:
    generated = "".join(next(unique_id_generator))

# Once an unused value has been found, add it to used list (or some sort of database where you can keep track)
used.add(generated)

此生成器将继续生成所有 ascii 小写字符和数字的所有可能组合(不替换),不包括您提到的那些。如果你需要这个大写,你可以使用.upper(),如果你想允许替换,你可以使用itertools.combinations_with_replacement

如果“xyz”被认为与“xzy”不同,请查看itertools.permutations

【讨论】:

  • 主要是,我想知道是否有一种方法可以在不检查前一个列表的情况下生成唯一值(理论上应该是可能的)。但从答案看来,python 不提供这样的功能。虽然这帮助我找到了我正在寻找的解决方案。我需要的是函数itertools.product()
【解决方案2】:

要对一组字符进行采样,您可以使用string.ascii_uppercase (A-Z) 加上string.digits (0-9),然后删除不需要的字符'LIO01'。从那里您可以使用random.choices 生成长度为k 的序列,同时允许重复字符。

import string
import random
def unique_id(size):
    chars = list(set(string.ascii_uppercase + string.digits).difference('LIO01'))
    return ''.join(random.choices(chars, k=size))

>>> unique_id(12)
'HBFXXHWZ8349'
>>> unique_id(12)
'A7W5WK636BYN'
>>> unique_id(12)
'WJ2JBX924NVK'

【讨论】:

  • 唯一性在哪里?虽然它是 12 个字符的可能性很小,但这可以生成两次相同的 id...
  • 最好添加某种验证,以确保您创建的 id 不会返回已经存在的 id(例如,如果您每次运行脚本一次)以避免ID 冲突问题。
  • 我不知道@ste_kwr 会将这些 ID 保存在哪里,我假设是某种数据库,因此需要这些细节来实现唯一性检查器。从高层次上看,它只是循环生成的 id,直到生成一个唯一的。
【解决方案3】:

我遇到了一个类似的问题,我能想到的最简单的解决方案就是这个:

回答

from secrets import token_urlsafe
id = ''.join([c for c in token_urlsafe(10) if c not in '-_OI0l'])[:5]

print(id) # 'a3HkR'

说明

token_urlsafe(10) 包含 10 个随机字符的字符串,来自 [az, AZ, 0-9, -, _]
if c not in '-_OI0l' 删除您不想要的字符
[:5] 从开头只取 5 个字符,例如,如果你想要 5 个。

优势

  • 可读
  • 单线
  • 可定制
  • 如果需要,可以高度安全

限制

  • 您可以通过其他方式检查唯一性,或者根据需要选择任意长的 id,以便随机性为您处理。

    • 以上示例可以创建 459 165 024 个不同的 id。
  • 如果您删除了许多字符或想要更多字符,您必须使token_urlsafe(number) 中的数字也更大,以免遇到IndexError

【讨论】:

    猜你喜欢
    • 2011-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-30
    • 2016-01-16
    相关资源
    最近更新 更多