我想以压缩格式存储以下元组的列表,我想知道哪种算法给了我
我的数据如下:
(<int>, <int>, <double>),
(<int>, <int>, <double>),
...
(<int>, <int>, <double>)
两个整数中的一个是指一个时间点,结果在一个列表中的数字很可能彼此接近。另一个int表示一个抽象id,值不太可能接近,尽管它们也不会完全随机。双精度表示传感器读数,虽然值之间存在某种相关性,但它可能没什么用处。
答案 0 :(得分:4)
由于“时间”整数可以彼此接近,因此尝试仅存储第一个和之后的差值,将差值保存到之前的(delta编码)。您也可以尝试使用第二个int。
您可以尝试的另一件事是将数据从[int1,int2,double],[int1,int2,double] ...重新组织为[int1,int1 ...],[int2,int2 ...] ,[双,双...]。
要查找结果所在的压缩范围,您可以将数据写入文件并从Christian Martelock here下载压缩程序CCM。我发现它对这样的数据收集表现得非常好。它使用非常快速的context mixing算法。您还可以将它与其他压缩器(如WinZIP)进行比较,或使用zLib等压缩库来查看是否值得付出努力。
答案 1 :(得分:2)
如果我正确地阅读了这个问题,您只需要有效地存储数据。显然,像压缩xml这样的简单选项很简单,但是有更多的直接二进制序列化方法。其中一个突飞猛进的是Google的protocol buffers。
例如,在带有protobuf-net的C#中,您只需创建一个类来保存数据:
[ProtoContract]
public class Foo {
[ProtoMember(1)]
public int Value1 {get;set;}
[ProtoMember(2)]
public int Value2 {get;set;}
[ProtoMember(3)]
public double Value3 {get;set;}
}
然后通过ProtoBuf.Serializer类[de]序列化List或Foo []等。
我并没有声称它会完全像节约自己一样节省空间,但它会非常接近。协议缓冲区规范相当好地利用了空间(例如,对整数使用base-128,这样小数字占用的空间更少)。但是尝试它会很简单,而不必自己编写所有的序列化代码。
这种方法虽然易于实现,但也具有易于从其他体系结构中使用的优点,因为various languages存在协议缓冲区实现。它还使用比常规[de]压缩(GZip / DEFLATE / etc)和/或基于xml的序列化少得多的CPU。
答案 2 :(得分:2)
大多数压缩算法对此类数据的处理效果都相同。但是,有一些事情(“预处理”)可以在将数据提供给gzip或deflate之类的算法之前增加数据的可压缩性。请尝试以下方法:
首先,如果可能,按升序对元组进行排序。首先使用抽象ID,然后使用时间戳。假设您有来自同一传感器的许多读数,则类似的ID将放在一起。
接下来,如果定期采取措施,则将时间戳替换为与先前时间戳的差异(当然,除了传感器的第一个元组除外)。例如,如果在5分钟时采取所有措施间隔,两个时间戳之间的增量通常接近300秒。因此,时间戳字段将更具可压缩性,因为大多数值都相等。
然后,假设测量值在时间上是稳定的,则将所有读数替换为相同传感器的先前读数的增量。同样,大多数值将接近零,因此更易于压缩。
此外,由于内部表示,浮点值是压缩的非常糟糕的候选者。尝试将它们转换为整数。例如,温度读数很可能不需要超过两位小数。将值乘以100并舍入为最接近的整数。
答案 3 :(得分:2)
这是在大多数搜索引擎中使用的常见方案:存储值的增量并使用可变字节编码方案对增量进行编码,即,如果增量小于128,则可以仅用1个字节编码。有关详细信息,请参阅Lucene中的vint和协议缓冲区。
这不会为您提供最佳的压缩比,但通常是编码/解码吞吐量最快的。
答案 4 :(得分:2)
按已提议的方式排序,然后存储
(第一期) (第二期) (双打)
转置矩阵。然后压缩
答案 5 :(得分:0)
很棒的答案,为了记录,我将合并那些我最终使用的方法:
对数据进行排序和重新组织,使相似的数字彼此相邻,即即首先按ID排序,然后按时间戳排序,然后从(<int1>, <int2>, <double>), ...
重新排列到([<int1>, <int1> ...], [<int2>, <int2> ... ], [<double>, <double> ...])
(按照建议排序)
schnaader和Stephan Leclercq
使用协议缓冲区进行序列化(我将在应用程序中使用它们,因此不会添加依赖项或任何内容)。感谢Marc Gravell指示我。