是否有推荐的算法将字符串缩短为一组元素(可能是数字和字符串的混合)
根据sawa的评论,没有这样的算法。
如果您有一组有限的允许字符串,则可以枚举它们并以合适的基数表示该数字。Base 64 有一个众所周知且得到良好支持的“url 安全”版本,非常适合表示 URL 路径内的任意压缩数据。
例如,只需获取您的整数订单 ID,它就已经是可枚举的了。如果您可以安全地假设最大允许值是 32 位整数,我们可以将其编码如下:
require 'base64'
number_to_encode = 1_234_567_890
compact_string = [number_to_encode].pack('N*') # Network byte order
encoded = Base64.urlsafe_encode64( compact_string )
# => "SZYC0g=="
这采用了一个最多 10 位数字的 id,并从中创建了一个包含 8 个字符的 url 字符串。要将其解码回您需要的数字:
require 'base64'
string_to_decode = "SZYC0g==" # e.g. params[:order_id] from /o/:order_id
packed_string = Base64.urlsafe_decode64( string_to_decode )
number = packed_string.unpack('N*').first
# => 1234567890
原则上,您可以通过这种方法表达任何类型的数据,前提是您可以在相关控制器中对其进行解包和消除歧义。但是,压缩有限制。您不能采用任意 32 位整数的参数,并将其放入 5 个 base64 字符(因为每个 base64 字符最多是 6 位数据)。
如果您需要像在 bit.ly 或 tinyurl.com 上看到的短 URL,那么可以通过创建一个可能的 URL 的大型查找表,并以与上面类似的方式对该表中的每一行编码 id 来完成此操作。或者,您可以将此数据存储为每个模型的唯一索引,并将序列号放入该列,或者生成随机字符串以测试其唯一性。所有这些方法本质上归结为有一组有限的引用来解决,将其转换为一个数字(项目的实际计数,或者选择低于理论最大值的唯一值),并使用像 Base64 这样的编码方案来表示与使用基数 10 相比,它的字符数更少。