我发现Marcel Jackwerth's对How to code a URL shortener?的回复是问题的一个很好的答案,但我的问题是它在PHP中的外观如何?这是Marcel's answer:
你需要一个Bijective Function f
(必须没有x1 != x2
,这将f(x1) = f(x2)
;而且每一个你都会找到斧头{{1} })。这是必要的,以便您可以为f(x)=y
函数找到反函数g('abc') = 123
。
我会继续您的“转换数字到字符串”方法(但是如果您的f(123)='abc'
是 prime 并且更高,您会意识到提议的算法会失败比52)。
如何将id
转换为缩短的网址
id
):例如125(十进制数) 如何将缩短的网址id
解析为初始abc
:
id
19158找到您的数据库记录。答案 0 :(得分: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');
答案 1 :(得分:0)
我喜欢这个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;
}
按照URL查找反向'解码'功能。
答案 2 :(得分:0)
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字符字典。
答案 3 :(得分:-1)
您需要做的就是在不同的基础系统基础10到基础62之间进行转换
https://github.com/infinitas/infinitas/blob/dev/core/short_urls/models/short_url.php