我有一个包含值1或0的数组,表示true或false值。 e.g。
array(1,0,0,1,0,1,1,1,1);
我希望将此数组压缩/编码为可能的最短字符串,以便将其存储在空间受限的位置(如cookie)中。它还需要能够在以后再次解码。我该怎么做?
PS。我在PHP工作
答案 0 :(得分:5)
以下是我的建议:
$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以便能够保存它作为一个字符串。
<强> UPD 强>:
相反的情况非常简单:
$original = str_split(implode('', array_map(function($i) {
return decbin(ord($i));
}, str_split(base64_decode($compressed)))));
我是如何编写它的(以防万一有人如何编写这样难以理解且几乎无法维护的代码):
我写了$original = $compressed;
并开始逐步颠倒这个表达式的右边部分:
答案 1 :(得分:0)
不要使用序列化。只需制作一个字符串:
<?php
$string = implode( '', $array );
?>
你留下了这样的字符串:
100101111
如果您想再次拥有一个数组,只需像数组一样访问它:
$string = '100101111';
echo $string[1]; // returns "0"
?>
当然你也可以把它设为小数,然后存储数字。这甚至比“原始”位短。
<?php
$dec = bindec( $string );
?>
答案 2 :(得分:0)
$arr = array(1,1,1,1,0,0,1,1,0,1,0,0,1,1,0,0,1,1,1,1);
$str = implode($arr);
$res = pack("h*", $str);
var_dump($res);
$rev = unpack("h*", $res);
var_dump($rev);
<强>输出:强>
string(10) # Not visible here
array(1) {
[1]=>
string(20) "11110011010011001111"
}
答案 3 :(得分:0)
这是我基于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;
}