【问题标题】:PHP implementation for an URL shortening algorithmURL缩短算法的PHP实现
【发布时间】:2011-02-01 10:18:43
【问题描述】:

我发现Marcel Jackwerth'sHow to code a URL shortener? 的响应可以很好地解决这个问题,但是我的问题是它在 PHP 中的外观如何?这里是Marcel's answer


你需要一个Bijective Functionf(必须没有x1 != x2,这将是f(x1) = f(x2);对于每个y,你都会找到一个x,这样f(x)=y)。这是必要的,这样您就可以为您的 f(123)='abc' 函数找到一个反函数 g('abc') = 123

我会继续您的“将数字转换为字符串”的方法(但是,如果您的 id素数 并且大于 52,您会意识到您的建议算法会失败)。

如何将id 转换为短网址:

  • 想一想您要使用的字母表。在您的情况下,这是 [a-zA-Z0-9]。它包含 62 个字母。
  • 获取自动生成的唯一数字键(自动递增 id):例如 125(十进制数)
  • 现在您必须将 125(以 10 为底)转换为 X(以 62 为底)。这将是 {2}{1} (2×62+1=125)。
  • 现在将符号 {2} 和 {1} 映射到您的字母表。说 {0} = 'a'、{25} = 'z' 等等。我们将有 {2} = 'c' 和 {1} = 'b'。所以 '/cb' 将是您缩短的网址。

如何将缩短的 url abc 解析为初始的 id

  • 如果你想反过来做,也不是很困难。 'e9a' 将被解析为“字母表中的第 4、61、0 个字母” = {4}{61}{0},即 4×62×62 + 61×62 + 0 = 19158。然后你只需要使用id 19158 查找您的数据库记录。

【问题讨论】:

    标签: php url


    【解决方案1】:
    function convert($src, $srcAlphabet, $dstAlphabet) {
        $srcBase = strlen($srcAlphabet);
        $dstBase = strlen($dstAlphabet);
    
        $wet = $src;
        $val = 0;
        $mlt = 1;
    
        while ($l = strlen($wet)) {
            $digit = $wet[$l - 1];
            $val += $mlt * strpos($srcAlphabet, $digit);
            $wet = substr($wet, 0, $l - 1);
            $mlt *= $srcBase;
        }
    
        $wet = $val;
        $dst = '';
    
        while ($wet >= $dstBase) {
            $digitVal = $wet % $dstBase;
            $digit = $dstAlphabet[$digitVal];
            $dst = $digit . $dst;
            $wet /= $dstBase;
        }
    
        $digit = $dstAlphabet[$wet];
        $dst = $digit . $dst;
    
        return $dst;
    }
    
    // prints cb
    print convert('125', '0123456789', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
    
    // prints 19158
    print convert('e9a', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', '0123456789');
    

    【讨论】:

    • 对不起,我忘了。重写了我的答案。
    【解决方案2】:

    我喜欢这个 PHP 函数,它允许您自定义字母表(并删除令人困惑的 0/O 等)

    // From http://snipplr.com/view/22246/base62-encode--decode/
    private function base_encode($val, $base=62, $chars='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') {
        $str = '';
        do {
            $i = fmod($val, $base);
            $str = $chars[$i] . $str;
            $val = ($val - $i) / $base;
        } while($val > 0);
        return $str;
    }
    

    按照网址也可以找到反向“解码”功能。

    【讨论】:

      【解决方案3】:

      Marcel 解决方案的主要问题是它使用零位作为占位符。通过在基数之间进行转换,所选择的表示 0 的数字不可避免地不能出现在转换后的数字的前面。

      例如,如果您使用提供的机制使用“ABCD”将基数为 10 的整数转换为基数 4,则无法获得以字母“A”开头的输出,因为它表示新基数中的零并且不会在号码前加前缀。您可能认为 5 是“AA”,但实际上它是“BA”。没有办法强制该算法生成“AA”,因为它就像用十进制写“00”,它的值与“0”相同。

      这是使用整个色域的 PHP 替代解决方案:

      function encode($n, $alphabet = 'ABCD') {
          $output = '';
      
          if($n == 0) {
              $output = $alphabet[0];
          }
          else {
              $digits = floor(log($n, strlen($alphabet))) + 1;
      
              for($z = 0; $z < $digits; $z++) {
                  $digit = $n % 4;
                  $output = $alphabet[$digit] . $output;
                  $n = floor($n / 4) - 1;
              }
          }
          return $output;
      }
      
      function decode($code, $alphabet = 'ABCD') {
          $n = 0;
          $code = str_split($code);
          $unit = 1;
          while($letter = array_pop($code)) {
              $n += (strpos($alphabet, $letter) + 1) * $unit;
              $unit = $unit * strlen($alphabet);
          }
      
          return $n - 1;
      }
      
      echo encode(25); // should output "ABB"
      echo decode('ABB'); // should output 25
      

      将第二个参数更改/传递给要使用的字符列表,而不是“ABCD”的 4 字符短字典。

      【讨论】:

        【解决方案4】:

        您需要做的就是在不同的基本系统之间转换 base 10 到 base 62

        https://github.com/infinitas/infinitas/blob/dev/core/short_urls/models/short_url.php

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-06-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-31
          相关资源
          最近更新 更多