Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python中唯一的十六进制短字符串_Python_Python 3.x_Uuid - Fatal编程技术网

Python中唯一的十六进制短字符串

Python中唯一的十六进制短字符串,python,python-3.x,uuid,Python,Python 3.x,Uuid,我需要在Python 3中生成一个唯一的十六进制字符串,该字符串满足以下要求: 它应该包含6个字符 它不应该只包含数字。必须至少有一个字符 这些生成的字符串应该是随机的。它们不应该按任何顺序排列 冲突的可能性应该是最小的 我考虑过uuid4()。但问题是,它生成的字符串包含太多字符,并且生成的字符串的任何子字符串在某个点上都可能包含所有数字(即没有字符) 有没有其他方法来满足这些条件?提前谢谢 编辑 我们可以使用哈希来满足上述要求吗?注意:更新了十六进制唯一字符串的答案。早些时候,我假设为alh

我需要在Python 3中生成一个唯一的十六进制字符串,该字符串满足以下要求:

  • 它应该包含6个字符
  • 它不应该只包含数字。必须至少有一个字符
  • 这些生成的字符串应该是随机的。它们不应该按任何顺序排列
  • 冲突的可能性应该是最小的
  • 我考虑过uuid4()。但问题是,它生成的字符串包含太多字符,并且生成的字符串的任何子字符串在某个点上都可能包含所有数字(即没有字符)

    有没有其他方法来满足这些条件?提前谢谢

    编辑


    我们可以使用哈希来满足上述要求吗?

    注意:更新了十六进制唯一字符串的答案。早些时候,我假设为alhanumeric字符串

    您可以使用
    uuid
    random
    库创建自己独特的函数

    >>> import uuid
    >>> import random
    # Step 1: Slice uuid with 5 i.e. new_id = str(uuid.uuid4())[:5] 
    # Step 2: Convert string to list of char i.e. new_id = list(new_id)
    >>> uniqueval = list(str(uuid.uuid4())[:5])
    # uniqueval = ['f', '4', '4', '4', '5']
    
    # Step 3: Generate random number between 0-4 to insert new char i.e.
    #         random.randint(0, 4)
    # Step 4: Get random char between a-f (for Hexadecimal char) i.e.
    #         chr(random.randint(ord('a'), ord('f')))
    # Step 5: Insert random char to random index
    >>> uniqueval.insert(random.randint(0, 4), chr(random.randint(ord('a'), ord('f'))))
    # uniqueval = ['f', '4', '4', '4', 'f', '5']
    
    # Step 6: Join the list
    >>> uniqueval = ''.join(uniqueval)
    # uniqueval = 'f444f5'
    

    注意:更新了十六进制唯一字符串的答案。早些时候,我假设为alhanumeric字符串

    您可以使用
    uuid
    random
    库创建自己独特的函数

    >>> import uuid
    >>> import random
    # Step 1: Slice uuid with 5 i.e. new_id = str(uuid.uuid4())[:5] 
    # Step 2: Convert string to list of char i.e. new_id = list(new_id)
    >>> uniqueval = list(str(uuid.uuid4())[:5])
    # uniqueval = ['f', '4', '4', '4', '5']
    
    # Step 3: Generate random number between 0-4 to insert new char i.e.
    #         random.randint(0, 4)
    # Step 4: Get random char between a-f (for Hexadecimal char) i.e.
    #         chr(random.randint(ord('a'), ord('f')))
    # Step 5: Insert random char to random index
    >>> uniqueval.insert(random.randint(0, 4), chr(random.randint(ord('a'), ord('f'))))
    # uniqueval = ['f', '4', '4', '4', 'f', '5']
    
    # Step 6: Join the list
    >>> uniqueval = ''.join(uniqueval)
    # uniqueval = 'f444f5'
    

    这里有一个简单的方法,可以从所有允许的字符串中均匀采样。统一采样使冲突尽可能少,除了保留以前密钥的日志或使用基于计数器的哈希(见下文)之外

    或者,这里有一种更为复杂的方法,它也可以统一采样,但不使用任何开放式循环:

    import random, bisect
    digits = '0123456789'
    letters = 'abcdef'
    all_chars = digits + letters
    length = 6
    
    # find how many valid strings there are with their first letter in position i
    pos_weights = [10**i * 6 * 16**(length-1-i) for i in range(length)]
    pos_c_weights = [sum(pos_weights[0:i+1]) for i in range(length)]
    
    # choose a random slot among all the allowed strings
    r = random.randint(0, pos_c_weights[-1])
    
    # find the position for the first letter in the string
    first_letter = bisect.bisect_left(pos_c_weights, r)
    
    # generate a random string matching this pattern
    val = ''.join(
        [random.choice(digits) for i in range(first_letter)]
        + [random.choice(letters)]
        + [random.choice(all_chars) for i in range(first_letter + 1, length)]
    )
    
    # now val is a suitable string
    print val
    # 4a99f0
    
    最后,这里有一个更复杂的方法,它使用随机数
    r
    直接索引到允许值的整个范围,也就是说,它将0-15777216范围内的任何数字转换成合适的十六进制字符串。这可以用来完全避免冲突(下文将详细讨论)

    这种方法产生11个结果的几率为0.5,或者01或10的几率为0.25,因此会增加11个结果之间发生碰撞的风险

    您可以尝试如下改进:做三个随机的二进制选择。第一个选项将按字符串中的原样使用。如果第一个选项为0,则第二个选项将转换为1;否则,它将按原样添加到字符串中。第三个选项将确定插入第二个选项的位置。那么你就有了以下可能的结果:

    0 0 0 -> 10 (second choice converted to 1)
    0 0 1 -> 01 (second choice converted to 1)
    0 1 0 -> 10
    0 1 1 -> 01
    1 0 0 -> 10
    1 0 1 -> 01
    1 1 0 -> 11
    1 1 1 -> 11
    
    这给01或10的机会为0.375,给11的机会为0.25。因此,这将略微增加重复10或01值之间冲突的风险

    减少冲突 如果您愿意使用所有字母,而不仅仅是“a”到“f”(十六进制数字),您可以按照注释中的说明更改
    字母的定义。这将提供更多不同的条件,减少冲突的机会。如果您生成了1000个允许所有大小写字母的字符串,那么生成任何副本的几率仅为0.0009%,而仅十六进制字符串的几率为3%。(这也将实际上消除通过循环的双通道。)

    如果确实希望避免字符串之间的冲突,可以将以前生成的所有值存储在
    集中
    并在中断循环之前进行检查。如果生成的密钥少于500万个,这将是很好的。除此之外,您还需要相当多的RAM来保存旧密钥,并且可能需要在循环中运行几次才能找到未使用的密钥


    如果需要生成更多的密钥,可以加密计数器,如中所述。计数器及其加密版本都是介于0到15777216之间的整数。计数器将从0开始计数,加密版本看起来就像一个随机数。然后使用上面的第三个代码示例将加密版本转换为十六进制。如果这样做,您应该在开始时生成一个随机加密密钥,并在每次计数器滚动超过最大值时更改加密密钥,以避免再次生成相同的序列。

    这里有一个简单的方法,可以从所有允许的字符串中均匀采样。统一采样使冲突尽可能少,除了保留以前密钥的日志或使用基于计数器的哈希(见下文)之外

    或者,这里有一种更为复杂的方法,它也可以统一采样,但不使用任何开放式循环:

    import random, bisect
    digits = '0123456789'
    letters = 'abcdef'
    all_chars = digits + letters
    length = 6
    
    # find how many valid strings there are with their first letter in position i
    pos_weights = [10**i * 6 * 16**(length-1-i) for i in range(length)]
    pos_c_weights = [sum(pos_weights[0:i+1]) for i in range(length)]
    
    # choose a random slot among all the allowed strings
    r = random.randint(0, pos_c_weights[-1])
    
    # find the position for the first letter in the string
    first_letter = bisect.bisect_left(pos_c_weights, r)
    
    # generate a random string matching this pattern
    val = ''.join(
        [random.choice(digits) for i in range(first_letter)]
        + [random.choice(letters)]
        + [random.choice(all_chars) for i in range(first_letter + 1, length)]
    )
    
    # now val is a suitable string
    print val
    # 4a99f0
    
    最后,这里有一个更复杂的方法,它使用随机数
    r
    直接索引到允许值的整个范围,也就是说,它将0-15777216范围内的任何数字转换成合适的十六进制字符串。这可以用来完全避免冲突(下文将详细讨论)

    这种方法产生11个结果的几率为0.5,或者01或10的几率为0.25,因此会增加11个结果之间发生碰撞的风险

    您可以尝试如下改进:做三个随机的二进制选择。第一个选项将按字符串中的原样使用。如果第一个选项为0,则第二个选项将转换为1;否则,它将按原样添加到字符串中。第三个选项将确定插入第二个选项的位置。那么你就有了以下可能的结果:

    0 0 0 -> 10 (second choice converted to 1)
    0 0 1 -> 01 (second choice converted to 1)
    0 1 0 -> 10
    0 1 1 -> 01
    1 0 0 -> 10
    1 0 1 -> 01
    1 1 0 -> 11
    1 1 1 -> 11
    
    这给01或10的机会为0.375,给11的机会为0.25。因此,这将略微增加重复10或01值之间冲突的风险

    减少冲突 如果您愿意使用所有字母,而不仅仅是“a”到“f”(十六进制数字),您可以按照注释中的说明更改
    字母的定义。这将提供更多不同的条件,减少冲突的机会。如果您生成了1000个允许所有大小写字母的字符串,那么生成任何副本的几率仅为0.0009%,而仅十六进制字符串的几率为3%。(这也将实际上消除通过循环的双通道。)

    如果你真的想避免co
    import random
    
    all = "0123456789abcdef"
    result = [random.choice('abcdef')] + [random.choice(all) for _ in range(4)]
    random.shuffle(result)
    result.insert(0, random.choice(all[1:]))
    print(''.join(result))
    
    3b7a4e
    
    def inttohex(number, digits):
        # there must be at least one character:
        fullhex = 16**(digits - 1)*6
        assert number < fullhex
        partialnumber, remainder = divmod(number, digits*6)
        charposition, charindex = divmod(remainder, digits)
        char = ['a', 'b', 'c', 'd', 'e', 'f'][charposition]
        hexconversion = list("{0:0{1}x}".format(partialnumber, digits-1))
        hexconversion.insert(charposition, char)
    
        return ''.join(hexconversion)
    
    import random
    
    digits = 6
    inttohex(random.randint(0, 6*16**(digits-1)), digits)