我有一个数组,其中包含代表真值或假值的 1 或 0 值。例如
array(1,0,0,1,0,1,1,1,1);
我想将此数组压缩/编码为可能的最短字符串,以便可以将其存储在空间受限的地方,例如 cookie。它还需要能够在以后再次解码。我该怎么做?
附言。我在 PHP 中工作
我有一个数组,其中包含代表真值或假值的 1 或 0 值。例如
array(1,0,0,1,0,1,1,1,1);
我想将此数组压缩/编码为可能的最短字符串,以便可以将其存储在空间受限的地方,例如 cookie。它还需要能够在以后再次解码。我该怎么做?
附言。我在 PHP 中工作
这是我的建议:
$a = array(1,0,0,1,0,1,1,1,1,1,0,0,1,0,1,1,1,1,1,0,0,1,0,1,1,1,1);
$compressed = base64_encode(implode('', array_map(function($i) {
return chr(bindec(implode('', $i)));
}, array_chunk($a, 8))));
var_dump($compressed); // string(8) "l8vlBw=="
因此,您获取每 8 个字符(实际上是二进制0..255
),将它们转换为整数,表示为 ASCII 字符,将其内爆为字符串并转换为 base64 以便能够将其保存为字符串。
更新:
相反的很简单:
$original = str_split(implode('', array_map(function($i) {
return decbin(ord($i));
}, str_split(base64_decode($compressed)))));
我到底是怎么写的(以防万一有人对如何编写这种不可读且几乎无法维护的代码感兴趣):
我已经编写$original = $compressed;
并开始逐步反转这个表达式的正确部分:
不要使用序列化。只需制作一个字符串:
<?php
$string = implode( '', $array );
?>
你会得到一个这样的字符串:
100101111
如果您想再次拥有一个数组,只需像访问数组一样访问它:
$string = '100101111';
echo $string[1]; // returns "0"
?>
当然,您也可以将其设为小数并仅存储数字。这甚至比“原始”位还要短。
<?php
$dec = bindec( $string );
?>
这是我基于 zerkms 答案的解决方案,它处理将小数转换回二进制时前导 0 的丢失。
function compressBitArray(array $bitArray){
$byteChunks = array_chunk($bitArray, 8);
$asciiString = implode('', array_map(function($i) {
return chr(bindec(implode('', $i)));
},$byteChunks));
$encoded = base64_encode($asciiString).'#'.count($bitArray);
return $encoded;
}
//decode
function decompressBitArray($compressedString){
//extract origional length of the string
$parts = explode('#',$compressedString);
$origLength = $parts[1];
$asciiChars = str_split(base64_decode($parts[0]));
$bitStrings = array_map(function($i) {
return decbin(ord($i));
}, $asciiChars);
//pad lost leading 0's
for($i = 0; $i < count($bitStrings); $i++){
if($i == count($bitStrings)-1){
$toPad = strlen($bitStrings[$i]) + ($origLength - strlen(implode('', $bitStrings)));
$bitStrings[$i] = str_pad($bitStrings[$i], $toPad, '0', STR_PAD_LEFT);
}else{
if(strlen($bitStrings[$i]) < 8){
$bitStrings[$i] = str_pad($bitStrings[$i], 8, '0', STR_PAD_LEFT);
}
}
}
$bitArray = str_split(implode('', $bitStrings));
return $bitArray;
}