【问题标题】:String of text to unique integer method?文本字符串到唯一整数方法?
【发布时间】:2015-10-20 12:36:02
【问题描述】:

有没有办法将'you'等一串文本转换成非数字

y = tuple('you')
for k in y:
  k = ord(k)

一次只转换一个字符?

【问题讨论】:

  • 您需要在转换后能够取回文本。
  • 从整数中取回文本?有可能,但这听起来像X-Y problem,你到底想达到什么目的?

标签: python python-3.x


【解决方案1】:

要将字符串转换为数字(反之亦然),您应该首先使用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'

【讨论】:

  • 这里的“小”是什么意思?
  • @AlihaydarGubatov 那是byte order, or endiannesslittle 是小端,big 是大端。
  • 是什么(如果有的话)促使您选择'little' byte_order?
  • @Syncrossus 你得选择字节序,所以我想我只是选择了little
【解决方案2】:
  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'

【讨论】:

  • 我在寻找一个数字,而不是代表整个单词的数字列表。
【解决方案3】:

将字符串视为 base-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 的答案基本相同,但明确编写而不是使用可用的方法在字节字符串和整数之间进行转换。)

【讨论】:

    【解决方案4】:

    我试图找到一种将 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')
    

    【讨论】:

      【解决方案5】:

      虽然有很多方法可以完成这项任务,但我更喜欢散列方式,因为它具有以下不错的属性

      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} \n\t[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
      

      【讨论】:

        猜你喜欢
        • 2013-05-07
        • 2019-07-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多