将文本字符串转换为唯一整数方法



是否存在将文本字符串(如'you')转换为除

以外的数字的方法?
y = tuple('you')
for k in y:
  k = ord(k)

一次只转换一个字符?

为了将字符串转换为数字(以及反过来),您应该首先始终使用bytes。由于您使用的是Python 3,字符串实际上是Unicode字符串,因此可能包含ord()值高于255的字符。然而,bytes每个字符只有一个字节;所以你应该首先在这两种类型之间进行转换。

所以基本上,你正在寻找一种方法来转换一个bytes字符串(这基本上是一个字节列表,一个0-255的数字列表)到一个单一的数字,反之亦然。您可以使用int.to_bytesint.from_bytes:

import math
def convertToNumber (s):
    return int.from_bytes(s.encode(), 'little')
def convertFromNumber (n):
    return n.to_bytes(math.ceil(n.bit_length() / 8), 'little').decode()
>>> convertToNumber('foo bar baz')
147948829660780569073512294
>>> x = _
>>> convertFromNumber(x)
'foo bar baz'

将字符串处理为基数为255的数字。

# Reverse the digits to make reconstructing the string more efficient
digits = reversed(ord(b) for b in y.encode())
n = reduce(lambda x, y: x*255 + y, digits)
new_y = ""
while n > 0:
    n, b = divmod(n, 255)
    new_y += chr(b)
assert y == new_y.decode()

(注意,这与poke的答案本质上是相同的,但是是显式编写的,而不是使用可用的方法在字节字符串和整数之间进行转换。)

  1. 您不需要将字符串转换为元组
  2. k被覆盖。使用列表推导式收集物品:

>>> text = 'you'
>>> [ord(ch) for ch in text]
[121, 111, 117]

要获得文本,使用chr,并使用str.join连接字符:

>>> numbers = [ord(ch) for ch in text]
>>> ''.join(chr(n) for n in numbers)
'you'

我试图找到一种方法将numpy字符数组转换为唯一的数字数组,以便做一些其他事情。我实现了以下函数,包括@poke和@falsetrue的答案(当字符串太大时,这些方法会给我带来一些麻烦)。我还添加了哈希方法(哈希是标识特定值的固定大小的整数)

import numpy as np
def str_to_num(x):
    """Converts a string into a unique concatenated UNICODE representation
    Args:
        x (string): input string
    Raises:
        ValueError: x must be a string
    """
    if isinstance(x, str):
        x = [str(ord(c)) for c in x]
        x = int(''.join(x))
    else:
        raise ValueError('x must be a string.')
    return x

def chr_to_num(x):
    return int.from_bytes(x.encode(), 'little')

def char_arr_to_num(arr, type = 'hash'):
    """Converts a character array into a unique hash representation.
    Args:
        arr (np.array): numpy character array.
    """
    if type == 'unicode':
        vec_fun = np.vectorize(str_to_num)
    elif type == 'byte':
        vec_fun = np.vectorize(chr_to_num)
    elif type == 'hash':
        vec_fun = np.vectorize(hash)    
    out = np.apply_along_axis(vec_fun, 0, arr)
    out = out.astype(float)
    return out
a = np.array([['x', 'y', 'w'], ['x', 'z','p'], ['y', 'z', 'w'], ['x', 'w','y'], ['w', 'z', 'q']])
char_arr_to_num(a, type = 'unicode')
char_arr_to_num(a, type = 'byte')
char_arr_to_num(a, type = 'hash')

虽然有许多方法可以完成此任务,但我更喜欢散列方法,因为它具有以下良好的属性

  1. 它确保你得到的数字是高度随机的,实际上是均匀随机的
  2. 它确保即使输入字符串的微小变化也会导致输出整数的显著差异。
  3. 这是一个不可逆的过程,也就是说,你不能根据整数输出来判断哪个字符串是输入。

    import hashlib
    # there are a number of hashing functions you can pick, and they provide tags of different lengths and security levels.
    hashing_func = hashlib.md5
    
    # the lambda func does three things
    # 1. hash a given string using the given algorithm
    # 2. retrive its hex hash tag
    # 3. convert hex to integer 
    str2int = lambda s : int(hashing_func(s.encode()).hexdigest(), 16) 

要查看生成的整数是如何均匀随机分布的,我们首先需要一些随机字符串生成器


    import string
    import numpy as np 
    # candidate characters
    letters = string.ascii_letters
    # total number of candidates
    L = len(letters)
    # control the seed or prng for reproducible results
    prng = np.random.RandomState(1234)
    
    # define the string prng of length 10
    prng_string = lambda : "".join([letters[k] for k in prng.randint(0, L, size=(10))])

现在我们生成足够数量的随机字符串并得到相应的整数


    ss = [prng_string() for x in range(50000)]
    vv = np.array([str2int(s) for s in ss])

让我们通过比较均匀分布的理论平均值和标准差与我们观察到的平均值和标准差来检查随机性。


    for max_num in [256, 512, 1024, 4096] :
        ints = vv % max_num
        print("distribution comparsions for max_num = {:4d} nt[theoretical] {:7.2f} +/- {:8.3f} | [observed] {:7.2f} +/- {:8.3f}".format(
            max_num, max_num/2., np.sqrt(max_num**2/12), np.mean(ints), np.std(ints)))

最后,您将看到下面的结果,这表明您得到的数字是非常一致的。

distribution comparsions for max_num =  256 
    [theoretical]  128.00 +/-   73.901 | [observed]  127.21 +/-   73.755
distribution comparsions for max_num =  512 
    [theoretical]  256.00 +/-  147.802 | [observed]  254.90 +/-  147.557
distribution comparsions for max_num = 1024 
    [theoretical]  512.00 +/-  295.603 | [observed]  512.02 +/-  296.519
distribution comparsions for max_num = 4096 
    [theoretical] 2048.00 +/- 1182.413 | [observed] 2048.67 +/- 1181.422

值得指出的是,其他发布的答案可能无法获得这些属性。

例如,@poke的convertToNumber解决方案将给出

distribution comparsions for max_num =  256 
    [theoretical]  128.00 +/-   73.901 | [observed]   93.48 +/-   17.663
distribution comparsions for max_num =  512 
    [theoretical]  256.00 +/-  147.802 | [observed]  220.71 +/-  129.261
distribution comparsions for max_num = 1024 
    [theoretical]  512.00 +/-  295.603 | [observed]  477.67 +/-  277.651
distribution comparsions for max_num = 4096 
    [theoretical] 2048.00 +/- 1182.413 | [observed] 1816.51 +/- 1059.643

最新更新