压缩冗余/重叠阵列数据

问题描述

想象一百万或更多的数组在数据上重叠(有时多有时少)。数据始终按升序排序。单个值占 2 个字节。

以下是一些示例:

[0,1,2,3,4]
[0,4,5]
[1,3]
[1,4]
[2,5]

我想可以执行某种替换:

A = [1,3]

[0,A,5]
[A]
[A,5]

这应该已经有很大帮助了,但也许不同的替代品可以节省更多?当然,行程编码也是一种选择,尽管由于大量的冗余信息,替代方法可能会产生更好的压缩。

其他要求:

  • 无损压缩
  • 解码/解压速度应该很快
  • 编码/压缩速度应该很快(尽管解码/解压缩速度更重要)
  • 随机访问数据

一个算法怎么能做到这一点?有什么更好的想法吗?真正的问题在于如何以占用最少空间的方式存储数据,同时仍然可以随时使用。

编辑: 数字并不总是连续的。它也可能看起来像这样:

[0,7,12,13,15]

然而数据不是随机的,而是显示重复序列。

解决方法

首先,是否需要压缩?如果数组大约有 10 个项目,每个数组大约有 44 个字节,那么一百万个数组将只有大约 44Mb,对于现代系统来说不是一个关键数量。

如果这太多了,我建议测试诸如 lz4 压缩之类的东西。这是为了快速,虽然它不允许随机访问,但它应该估计数据压缩的效率。

对于小数组,对象开销可能比数据本身占用更多内存。如果您不需要添加/删除项目,您可以考虑采用某种方案将所有数据保留一两个列表。例如,将所有数字添加到一个连续数组中,并使用偏移/长度表示每个子数组的结构。这应该可以让您显着减少开销。如果您想返回一个没有任何复制的序列,请使用 Memory<T>Span<T>

如果可能,这还可以方便地让您重用现有序列。只需按排序顺序添加序列,最长的在前,然后进行搜索以查看该序列是否已被表示。在您的示例中,包括非连续示例,我们可以将序列表示如下:

numbers: [0,1,2,3,4,5,7,12,13,15]
offset:0 length: 5
offset:0 length: 6
offset:1 length: 3
offset:1 length: 4
offset:2 length: 4
offset:6 length: 6

您建议的替换方案的一个问题是,如果每个项目没有数组似乎很难做到,并且至少使用 32 个字节,所以如果每个数组都很短,那就不是很好,但如果数组可能会更好明显长于您的示例。