Javascript 有没有可靠地压缩短字符串的方法?

Javascript 有没有可靠地压缩短字符串的方法?,javascript,string,encoding,compression,query-string,Javascript,String,Encoding,Compression,Query String,我有一个正好53个字符长的字符串,其中包含一组有限的可能字符 [A-Za-z0-9\.\-~_+]{53} 我需要在不丢失信息和使用相同字符集的情况下将其长度减少到50 [A-Za-z0-9\.\-~_+]{53} 我认为应该可以将大多数字符串压缩到50个长度,但是否可以将所有可能的长度压缩到53个字符串?我们知道,在最坏的情况下,可能集合中的14个字符将不被使用。我们能利用这些信息吗 谢谢你的阅读 是一个简单的压缩库,适合压缩非常短的字符串。如果我没记错的话,它将是存储数据的最紧凑的方式。

我有一个正好53个字符长的字符串,其中包含一组有限的可能字符

[A-Za-z0-9\.\-~_+]{53}
我需要在不丢失信息和使用相同字符集的情况下将其长度减少到50

[A-Za-z0-9\.\-~_+]{53}

我认为应该可以将大多数字符串压缩到50个长度,但是否可以将所有可能的长度压缩到53个字符串?我们知道,在最坏的情况下,可能集合中的14个字符将不被使用。我们能利用这些信息吗

谢谢你的阅读

是一个简单的压缩库,适合压缩非常短的字符串。

如果我没记错的话,它将是存储数据的最紧凑的方式。我已经很久没有用它来快速编写算法了,但基本思想已经涵盖在内,但如果我没记错的话,你所做的是:

  • 获取所使用的每个字符的计数
  • 根据它们发生的频率对它们进行优先排序
  • 根据优先顺序构建一棵树
  • 通过遍历树获取每个字符的压缩位表示(从根开始,左=0右=1)
  • 用树中的位替换每个字符

  • 在最普遍的情况下,你所问的是不可能的,这可以很简单地证明

    假设可以在同一集中将任意53个字符的字符串编码为50个字符。这样做,然后向编码字符串添加三个随机字符。然后是另一个任意的53个字符的字符串。你怎么压缩它

    因此,您想要的东西不能保证对任何可能的数据都有效。然而,你所有的真实数据都有可能具有足够低的熵,你可以设计出一个可行的方案

    在这种情况下,您可能需要执行哈夫曼编码的一些变体,它基本上为集合中的字符分配可变位长度编码,对最常用的字符使用最短的编码。您可以分析所有数据,得出一组编码。在哈夫曼编码之后,您的字符串将是一个(希望更短)比特流,您可以将其编码为每个字符6位的字符集。它可能对所有真实数据都足够短

    基于库的编码,如Smaz(在另一个答案中引用)也可以工作。同样,不可能保证它对所有可能的数据都有效。

    一个字节(字符)可以编码256个值(0-255),但您的有效字符集只使用67个值,这些值可以用7位表示(唉,6位只能表示64位),并且您的字符中没有一个使用字节的高位

    因此,您可以丢弃高位,只存储7位,将下一个字符的初始位运行到第一个字符的“空闲”空间中。这只需要47字节的空间来存储。(53 x 7=371位,371/8=46.4==47)

    这并不是真正意义上的压缩,而是编码的改变

    例如,“ABC”是0x41 0x42 0x43

         0x41        0x42        0x43  // hex values
    0100 0001   0100 0010   0100 0011  // binary
     100 0001    100 0010    100 0011  // drop high bit
    // run it all together
    100000110000101000011
    // split as 8 bits (and pad to 8)
    10000011   00001010   00011[000]
        0x83       0x0A        0x18
    
    例如,这3个字符不会节省任何空间,但您的53个字符将始终显示为47个,这是有保证的

    但是,请注意,如果对您很重要,输出将不在原始字符集中

    这个过程变成:

    original-text --> encode --> store output-text (in database?)
    retrieve --> decode --> original-text restored
    

    如您所述,如果您的输出字符串必须使用与输入字符串相同的字符集,并且如果您不知道输入字符串的任何特殊要求,则不可能将所有可能的53个字符字符串压缩为50个字符。这是的一个简单应用程序

    • 您的输入字符串可以表示为67中的53位数字,即0到6753-1之间的整数≅ 6*1096
    • 您希望将这些数字映射为0到6750-1之间的整数≅ 2*1091
    • 所以根据鸽子洞原理,你可以保证673=300763个不同的输入会映射到每个可能的输出——这意味着,当你去解压时,你无法知道你应该映射回哪个300763原稿
    要使此工作正常,您必须更改您的需求。您可以使用更大的字符集对输出进行编码(如果每个字符都有87个可能的值,而不是输入中的67个,则可以将其减少到50个字符)。或者你可以识别输入中的冗余——也许第一个字符只能是'3'或'5',第十九个和第二十个是州缩写,只能有62个不同的可能值,诸如此类


    如果你不能做到这两件事中的任何一件,你就必须使用压缩算法,比如哈夫曼编码,并接受这样一个事实,即某些字符串是可压缩的(并且会变短),而另一些则不会(并且会变长)。

    “我们知道,在最坏的情况下,可能的字符串集中的14个字符将被闲置。”你能详细说明一下吗?我相信这里需要的是编码,而不是编码compression@JohnKugelman53个字符的字符串,每个字符不同。67个可能的字符(52个字母、10个数字、5个符号)。67-53=14未使用。@pst谢谢,我已经添加了它作为标记。我认为这在每个字符都不同的情况下不起作用。据我所知,第一次出现的字符需要按照常规编码,然后将其添加到内部树结构中。这是真的,您确实需要编码转换为什么的前导表示,因此,它可能无法处理像您正在使用的字符串那样短的字符串。请检查问题。一旦再次使用字符集对结果进行编码,您是否可以确保这将对该字符集中的每一个可能长度53个字符串压缩3个字符?查看示例,这可能不适用于此输入,因为smaz仅压缩自然语言很好,因为它使用字典而不是通用算法。不幸的是,只有ASCII输入