【问题标题】:Encoding a numeric string into a shortened alphanumeric string, and back again将数字字符串编码为缩短的字母数字字符串,然后再返回
【发布时间】:2012-05-06 18:06:50
【问题描述】:

快速提问。我正在尝试在 Python 中查找或编写一个编码器,以通过使用大小写字母来缩短一串数字。数字字符串看起来像这样:

20120425161608678259146181504021022591461815040210220120425161608667

长度始终相同。

我最初的想法是写一些简单的编码器来利用大小写字母和数字来缩短这个字符串,看起来更像这样:

a26Dkd38JK

这完全是武断的,只是想尽可能清楚。 我确信有一种非常巧妙的方法可以做到这一点,可能已经内置了。也许这是一个令人尴尬的问题。

另外,我需要能够获取缩短的字符串并将其转换回更长的数值。 我应该写一些东西并发布代码,还是这是我应该已经知道的 Python 内置函数?

谢谢!

【问题讨论】:

  • JBernardo- 确定了它。将其发布为答案:)!!
  • 您愿意自己编写代码并将其发布在此处,这是一件好事。
  • (其实只是单独使用base64实际上会拉长字符串)
  • JBernardo - 感谢您的建议,但正如 David 指出的那样,使用 base64 并不能解决我的问题,因为它实际上会显着延长字符串。这里的目标是缩短它。

标签: python string encode numeric


【解决方案1】:

这是一个很好的压缩:

import base64

def num_to_alpha(num):
    num = hex(num)[2:].rstrip("L")

    if len(num) % 2:
        num = "0" + num

    return base64.b64encode(num.decode('hex'))

它首先将整数转换为字节串,然后对其进行 base64 编码。这是解码器:

def alpha_to_num(alpha):
    num_bytes = base64.b64decode(alpha)
    return int(num_bytes.encode('hex'), 16)

例子:

>>> num_to_alpha(20120425161608678259146181504021022591461815040210220120425161608667)
'vw4LUVm4Ea3fMnoTkHzNOlP6Z7eUAkHNdZjN2w=='
>>> alpha_to_num('vw4LUVm4Ea3fMnoTkHzNOlP6Z7eUAkHNdZjN2w==')
20120425161608678259146181504021022591461815040210220120425161608667

【讨论】:

  • 这看起来效果很好。正是我想要的,谢谢。 RE:int vs. string:将字符串传递给这个函数实际上是行不通的。它确实需要是一个int。干得好!
  • 这需要任意精度的整数,幸运的是python有。
  • @ninjagecko:我不明白为什么这需要任意精度的整数。它适用于它们 - 当然 - 但给定函数中没有任何部分依赖于任意精度整数。
  • @nightcracker:是的。您将整数作为输入这一事实足以作为需要任意精度整数的理由。您可以通过尝试使用另一种语言(例如 javascript)来自己测试,而无需使用任意精度的整数。足够大的输入将毫无意义。这并不是说这会使其他语言的答案不合理;答案适用于任何不溢出的输入。通常不是问题,但 OP 使用的是在大多数非 python 语言中会溢出的数字字符串。
  • @ninjagecko:啊,现在我明白你的意思了。
【解决方案2】:

有两个函数是自定义的(不是基于base64),但会产生更短的输出:

chrs = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = len(chrs)

def int_to_cust(i):
    result = ''
    while i:
        result = chrs[i % l] + result
        i = i // l
    if not result:
        result = chrs[0]
    return result

def cust_to_int(s):
    result = 0
    for char in s:
        result = result * l + chrs.find(char)
    return result

结果是:

>>> int_to_cust(20120425161608678259146181504021022591461815040210220120425161608667)
'9F9mFGkji7k6QFRACqLwuonnoj9SqPrs3G3fRx'
>>> cust_to_int('9F9mFGkji7k6QFRACqLwuonnoj9SqPrs3G3fRx')
20120425161608678259146181504021022591461815040210220120425161608667L

如果您将其他字符添加到chrs 变量中,您还可以缩短生成的字符串。

【讨论】:

  • 我猜你是在自己做base 64编码而不是使用lib。
  • @PaulHoang:我猜你的猜测是错误的。我介绍了以类似方式工作的函数,但是 1) 不需要填充(尝试从 nightcracker 的答案中删除 =s),2) 能够定义用于表示转换值的自己的字符。它的工作方式与base64非常相似,但不是base64。可能有一个库可以做类似的事情,但没有找到它。
  • 我真的很喜欢这个解决方案。在尝试各种建议的解决方案时,我最喜欢这个,因为我可以将其限制为字母和数字,并且可以控制将来添加更多字符。做得很好。
【解决方案3】:

用“类”来做:

VALID_CHRS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
BASE = len(VALID_CHRS)
MAP_CHRS = {k: v
            for k, v in zip(VALID_CHRS, range(BASE + 1))}


class TinyNum:
    """Compact number representation in alphanumeric characters."""

    def __init__(self, n):
        result = ''
        while n:
            result = VALID_CHRS[n % BASE] + result
            n //= BASE
        if not result:
            result = VALID_CHRS[0]
        self.num = result

    def to_int(self):
        """Return the number as an int."""
        result = 0
        for char in self.num:
            result = result * BASE + MAP_CHRS[char]
        return result

示例用法:

>> n = 4590823745
>> tn = TinyNum(a)
>> print(n)
4590823745
>> print(tn.num)
50GCYh
print(tn.to_int())
4590823745

(基于Tadeck's answer。)

【讨论】:

    【解决方案4】:
    >>> s="20120425161608678259146181504021022591461815040210220120425161608667"
    >>> import base64, zlib
    >>> base64.b64encode(zlib.compress(s))
    'eJxly8ENACAMA7GVclGblv0X4434WrKFVW5CtJl1HyosrZKRf3hL5gLVZA2b'
    >>> zlib.decompress(base64.b64decode(_))
    '20120425161608678259146181504021022591461815040210220120425161608667'
    

    所以 zlib 在压缩数字字符串方面并不聪明:(

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-01
      • 1970-01-01
      • 2014-10-24
      • 2021-08-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多