PHP Compress array of bits into shortest string possible

ぐ巨炮叔叔 提交于 2021-02-10 05:44:26

问题


I have an array that contains values of 1 or 0 representing true or false values. e.g.

array(1,0,0,1,0,1,1,1,1);

I want to compress/encode this array into the shortest string possible so that it can be stored within a space constrained place such as a cookie. It also need to be able to be decoded again later. How do I go about this?

ps. I am working in PHP


回答1:


Here is my proposal:

$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=="

So you get each 8 characters (which in fact is a binary 0..255), convert them to an integer, represent as an ASCII character, implode it to a string and convert to base64 to be able to save it as a string.

UPD:

the opposite is pretty straightforward:

$original = str_split(implode('', array_map(function($i) {
    return decbin(ord($i));
}, str_split(base64_decode($compressed)))));

How exactly I wrote it (just in case anyone interesting how to write such unreadable and barely maintainable code):

I've written the $original = $compressed; and started reversing the right part of this expression step by step:

  1. Decoded from base64 to a binary string
  2. Split it to an array
  3. Converted every character to its ASCII code
  4. Converted decimal ASCII code to a binary
  5. Joined all the binary numbers into a single one
  6. Split the long binary string to an array



回答2:


Dont use serialize. Just make a string of it:

<?php

$string = implode( '', $array );
?>

You are left with an string like this:

100101111

If you want to have an array again, just access it like an array:

$string = '100101111';

echo $string[1]; // returns "0"

?>

Of course you could also make it a decimal and just store the number. That's even shorter then the "raw" bits.

<?php

$dec = bindec( $string );

?>



回答3:


How about pack and unpack

$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);

output:

string(10) # Not visible here
array(1) {
  [1]=>
  string(20) "11110011010011001111"
}



回答4:


Here is my solution based on zerkms answer, this deals with the loss of leading 0's when converting decimals back into binary.

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;
}


来源:https://stackoverflow.com/questions/15023213/php-compress-array-of-bits-into-shortest-string-possible

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!