我现有"压缩"算法,将关联压缩为范围。像
这样的东西type Assoc = [(P,C)]
type RangeCompress :: Assoc -> [(P, [(C,C)]]
将P视为"产品"和C作为"代码"。结果是每个与代码范围列表相关联的产品列表。要查找与给定代码关联的产品,可以遍历压缩数据,直到找到范围,给定代码落入。
如果连续代码可能属于同一产品,则此机制很有效。然而,如果不同产品的代码交错,它们不再形成紧凑的范围,并且我最终得到许多范围,其中上限等于下限和零压缩。
我正在寻找的是一个预压缩器,它会查看原始关联并确定一个足够好的"代码转换,使得根据转换代码表示的关联可以被范围压缩到紧凑范围。像
这样的东西preCompress :: Assoc -> (C->C)
或更细粒度(按产品)
preCompress ::Assoc -> P -> (C->C)
在这种情况下,产品查询必须首先转换相关代码,然后像以前一样进行查找。因此,转换必须通过少数参数表达,这些参数必须附加到压缩数据,一次用于整个关联或按产品。
我检查了一些压缩算法,但它们似乎都专注于重建原始数据(这里不是严格需要的),同时完全没有关于它们存储压缩数据的方式。但在我的情况下,压缩数据必须是范围,只能通过预压缩的参数进行丰富。
请注意:
答案 0 :(得分:1)
假设每个代码只有一个产品,您可以将数据编码为产品列表(字符串)。让我们假设我们有9个产品(或没有产品)和10个代码随机生成的以下产品和代码列表。
[(P6,C2),
(P1,C4),
(P2,C10),
(P3,C9),
(P3,C1),
(P4,C7),
(P6,C8),
(P5,C3),
(P1,C5)]
如果我们按代码对它们进行排序
[(P3,C1),
(P6,C2),
(P5,C3),
(P1,C4),
(P1,C5),
-- C6 didn't have a product
(P4,C7),
(P6,C8),
(P3,C9),
(P2,C10)]
我们可以将其转换为一串产品+一无所有(N
)。字符串中的位置决定了代码。
{- C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 -}
[ P3, P6, P5, P1, P1, N , P4, P6, P3, P2 ]
一些字母表中的一串符号(在这种情况下是产品+没有)使我们完全处于充分研究的字符串压缩问题的范围内。
如果我们run-length encode此列表,我们的编码类似于您最初提供的编码。对于每个关联范围,我们存储单个产品+无和运行长度。我们只需要一个小的整数用于运行长度而不是两个(可能是大的)代码。
{- P3 , P6, P5, P1, P1, N , P4, P6, P3, P2 -}
[ (P3, 1), (P6, 1), (P5, 1), (P1, 2), (N, 1), (P4, 1), (P6, 1), (P3, 1), (P2, 1) ]
我们可以将其序列化为一个字节字符串,并使用任何现有的compression libraries字节来执行实际压缩。某些压缩库(例如常用的zlib)位于codec category。
中我们将从之前获取相同的数据,并按产品而不是代码
对其进行排序[(P1,C4),
(P1,C5),
(P2,C10),
(P3,C1),
(P3,C9),
(P4,C7),
(P5,C3),
(P6,C2),
(P6,C8)]
我们希望为每个产品分配新代码,以便产品的代码始终是连续的。我们只是按顺序分配这些代码。
-- v-- New code --v v -- Old code
[(P1,C1), [(C1,C4)
(P1,C2), (C2,C5),
(P2,C3), (C3,C10),
(P3,C4), (C4,C1),
(P3,C5), (C5,C9),
(P4,C6), (C6,C7),
(P5,C7), (C7,C3),
(P6,C8), (C8,C2),
(P6,C9), (C9,C8)]
我们现在有两个要保存的数据。我们在产品和代码范围之间进行(现在)一对一映射,并在新代码和旧代码之间进行新的一对一映射。如果我们按照上一节中的步骤操作,我们可以将新代码和旧代码之间的映射转换为旧代码列表。列表中的位置决定了新代码。
{- C1 C2 C3 C4 C5 C6 C7 C8 C9 -} -- new codes
[ C4, C5, C10, C1, C9, C7, C3, C2, C8 ] -- old codes
我们可以将任何现有的压缩算法抛出此字符串。每个符号在此列表中最多只出现一次,因此传统的压缩机制将不再压缩此列表。这与产品分组和将代码列表存储为产品阵列没有显着差异;新的中间代码只是(更大)指向数组开头和数组长度的指针。
[(P1,[C4,C5]),
(P2,[C10]),
(P3,[C1,C9]),
(P4,[C7]),
(P5,[C3]),
(P6,[C2,C8])]
旧代码列表的更好表示可能是旧代码之间的差异。如果代码已经倾向于处于连续范围内,则这些连续范围可以进行行程编码。
{- C4, C5, C10, C1, C9, C7, C3, C2, C8 -} -- old codes
[ +4, +1, +5, -9, +8, -2, -4, -1, +6 ] -- old code difference
我可能想要存储产品差异以及代码与产品的差异。这应该增加了最终压缩算法压缩的公共子串的机会。
[(+1,[+4,+1]),
(+1,[+5]),
(+1,[-9,+8]),
(+1,[-2]),
(+1,[-4]),
(+1,[-1,+6])]