【问题标题】:Encode/compress sequence of repeating integers编码/压缩重复整数序列
【发布时间】:2011-02-03 17:41:44
【问题描述】:

我有很长的整数序列,看起来像这样(任意长度!):

0000000001110002220033333

现在我需要一些算法将这个字符串转换成压缩的东西,比如

a9b3a3c3a2d5

表示“a 9 次,b 3 次,a 3 次”等等,其中“a”代表 0,“b”代表 1,“c”代表 2,“d”代表 3。

你会怎么做? 到目前为止,我没有想到任何合适的东西,而且我在谷歌上没有运气,因为我真的不知道要搜索什么。这种编码/压缩叫什么?

PS:我将使用 PHP 进行编码,并使用 JavaScript 进行解码。

编辑:谢谢大家!

我最终得到了这个用于编码的函数:

protected function numStringToRle($s){          
        $rle    = '';
        $count = 1;
        $len    = strlen($s);
        for($i = 0; $i < $len; $i++){
            if($i != $len && isset($s[$i+1]) && $s[$i] == $s[$i+1]){
                $count++;                
            } else {
                $rle .= chr($s[$i] + 97).( $count == 1 ? '' : $count);                                
                $count = 1;
            }
        }
        return $rle;            
}

还有用于解码的:

var decodeCoords = function(str) {

   str = str.replace(/(.)(\d+)/g, function(_, x, n) {
       return new Array(parseInt(n, 10) + 1).join(x);
   });

   return str.
     replace(/a/g, '0').
     replace(/b/g, '1').
     replace(/c/g, '2').
     replace(/d/g, '3');     
};

【问题讨论】:

  • 你到底在用这个做什么?你确定你不能只使用 Gzip 压缩它吗? stackoverflow.com/questions/294297/… 这样在时间和空间上都会更有效率,而且已经为你做好了。
  • gzip 不是一个选项,因为我需要使用 javascript 对其进行解码。我将它用作 2d 游戏的一种位掩码。

标签: php javascript sequence encode compression


【解决方案1】:

Run Length Encoding

PHP 中的基本编码器:

function numStringToRle($s){
    $rle = '';
    $count = 1;
    $len = strlen($s);
    for ( $i = 0; $i < $len; $i++ ){
        if ( $i != $len && $s[$i] == $s[$i+1] ){
            $count++;                
        }else{
          $rle .= chr($s[$i] + 97).$count;    
          $count = 1;
        }
    }
    return $rle;
}

请注意,这样的字符串会导致严重问题

 123456789123456789

如果您要处理的字符串可能包含许多单独的单个字符,则最好添加一些复杂性,并且如果运行长度为 1,则不要写运行长度。

//change
$rle .= chr($s[$i] + 97).$count;    

//to
$rle .= chr($s[$i] + 97).( $count == 1 ? '' : $count );   

//or
$rle .= chr($s[$i] + 97)
if ( $count != 1 ){
    $rle .= $count;
}

【讨论】:

  • 我在找这个算法的名字。谢谢!
  • 能否请您详细说明+97,这是做什么的,为什么需要它?
【解决方案2】:

这是你想要的一个简单的实现。

$toEncode = '0000000001110002220033333';
$currentChar = '-1';
$length = strlen($toEncode);
$encoded = '';
$currentNbrChar = 0;
for($i = 0; $i < $length; $i++){
  if($toEncode[$i] != $currentChar){
    if($currentChar != '-1'){
      $encoded .= chr(97 + $currentChar).$currentNbrChar;
    }
    $currentNbrChar = 0;
    $currentChar = $toEncode[$i];
  }
  $currentNbrChar ++;
}
if($currentChar != '-1'){
  $encoded .= chr(97 + $currentChar).$currentNbrChar;
}
echo $encoded;

【讨论】:

    【解决方案3】:

    这是一个较短的版本:

    function smush(str) {
      return str.replace(/((.)\2*)/g, function(_, w, x) {
        return x + w.length;
      });
    }
    

    edit 哦,我看到你想用 php 编码;对不起,我不知道。这是一个具有类似精神的解码器:

    function unsmush(str) {
      return str.replace(/(.)(\d+)/g, function(_, x, n) {
        return new Array(parseInt(n, 10) + 1).join(x);
      });
    }
    

    【讨论】:

      【解决方案4】:

      仅供参考,您可能会 gzip 您的数据,浏览器会自动解压缩它。对于大多数实现,这将比 RLE 更好地工作。但显然没那么有趣。

      【讨论】:

        【解决方案5】:
        $str="0000000001110002220033333";
        
        //$c will count the number of occurances.
        
        $c=1;
        
        $lastInt=substr($str,0,1);
        
        $str=substr($str,1);
        
        $resultStr='';
        
        $loopEnd=strlen($str);
        
        
        for($i=1; $i<=$loopEnd+1;$i++)
        
        {
        
            $nowInt=substr($str,0,1);   
            if($lastInt==$nowInt)
            {
                $c++;
                $str=substr($str,1);
            }
            else
            {
                $char=chr((int)$lastInt + 97);
                $resultStr=$resultStr.$char.$c;
                $str=substr($str,1);
                $c=1;
                $lastInt=$nowInt;
            }
        }
        
        // we use if condition since for loop will not take the last integer if it repeats.
        
        if($c>1)
        {
        
        $char=chr((int)$lastInt + 97);
        
        $resultStr=$resultStr.$char.$c;
        
        }
        
        echo $resultStr;
        

        【讨论】:

          【解决方案6】:
          function compress( $str) {
          $strArr = str_split($str.'0');
          $count = 0;
          $resStr = '';
          $strCheck = $strArr[0];
          foreach($strArr as $key => $value)
          {
              if($strCheck == $value)
              {
                 $count++;
              } 
              else
              {
                  if($count == 1)
                  {
                      $strCheck = $value;
                      $resStr .= $strArr[$key-1];
                      $count=1;
                  }
                  elseif($count == 2)
                  {
                      $strCheck = $value;
                      $resStr .= $strArr[$key-1].$strArr[$key-1];
                      $count=1;
                  }
                  else
                  {
                      $strCheck = $value;
                      $resStr .= $strArr[$key-1].$count;
                      $count=1;
                  }
              } 
          
          } 
          return $resStr;
          

          }

          【讨论】:

            猜你喜欢
            • 2012-08-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-11-09
            • 2010-09-21
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多