2

true または false の値を表す 1 または 0 の値を含む配列があります。例えば

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

この配列を可能な限り短い文字列に圧縮/エンコードして、Cookie などのスペースに制約のある場所に格納できるようにしたいと考えています。また、後で再度デコードできるようにする必要もあります。どうすればいいですか?

ps。私はPHPで働いています

4

4 に答える 4

6

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
于 2013-02-22T11:39:27.770 に答える
0

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

?>
于 2013-02-22T11:37:34.263 に答える
0

これが zerkms の回答に基づく私の解決策です。これは、10 進数を 2 進数に変換するときに先頭の 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;
}
于 2013-02-22T14:09:33.777 に答える
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"
}
于 2013-02-22T13:25:12.353 に答える