【问题标题】:Compress redundant/overlapping array data压缩冗余/重叠数组数据
【发布时间】:2021-09-20 14:36:41
【问题描述】:

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

这里有一些例子:

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

我想可以执行某种替换:

A = [1, 2, 3]

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

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

附加要求:

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

这样的算法看起来如何?有更好的想法吗?真正的问题在于如何以一种占用最少空间同时仍然随时可用的方式存储数据。

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

[0, 1, 7, 12, 13, 15]

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

【问题讨论】:

  • 数字总是连续的吗?
  • 没有。可以有 [0, 1, 7, 12, 13, 15] 之类的间隙
  • 您需要决定要支持的阵列数量。如果它是一百万(大约 2^20),使用 A、B、... 不会削减它。您是否尝试过仅使用 ZIP 压缩,IIRC,它非常擅长处理运行
  • 我没有,因为我仍然需要允许随机访问。虽然也许值得将数据分块(但也会再次降低压缩率)。

标签: c# arrays algorithm compression lossless-compression


【解决方案1】:

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

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

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

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

numbers: [0, 1, 2, 3, 4, 5, 0, 1, 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 个字节,因此如果每个数组都很短,则不是很好,但如果数组可能更好比你的例子长得多。

【讨论】:

  • 我已经设法通过使用运行长度编码并为 delta 存储单个字节来大大减少大小,但我仍在尝试查看是否有可能更大的节省,因为冗余数据在这里看起来非常可利用。你的想法看起来很有趣,我自己也没有想过这样的方法。
  • 数组可能会更长。但是我不确定如何最好地找到重复序列,因为如果我只是对内容进行哈希处理,我只会找到完美匹配,即使可能只有一个额外的数字在另一个数组中,等等。我猜有很多排列.
猜你喜欢
  • 1970-01-01
  • 2013-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-23
  • 2011-01-17
相关资源
最近更新 更多