我想建立一個URL縮短服務,您能夠在其中將長URL寫入輸入字段,而後該服務將URL縮短爲「 http://www.example.org/abcdef
」。 php
除了「 abcdef
」以外,還能夠有其餘任何六個字符串,包含az, AZ and 0-9
。 這使得56〜570億個可能的字符串。 java
個人方法: git
我有一個包含三列的數據庫表: github
而後,我將長網址插入表中。 而後,我將爲「 id
」選擇自動增量值,併爲其構建一個哈希值。 而後應將此散列插入爲「 short
」。 可是我應該創建什麼樣的哈希? 像MD5這樣的哈希算法建立的字符串太長。 我認爲我不使用這些算法。 自建算法也將起做用。 算法
個人點子: 數據庫
對於「 http://www.google.de/
」,我獲得了自動增量ID 239472
。 而後,我執行如下步驟: app
short = ''; if divisible by 2, add "a"+the result to short if divisible by 3, add "b"+the result to short ... until I have divisors for a-z and A-Z.
能夠重複進行直到該數字再也不可除。 您認爲這是個好方法嗎? 你有更好的主意嗎? ide
因爲對該主題的持續關注,我爲GitHub發佈了一種有效的解決方案 ,其中包含JavaScript , PHP , Python和Java的實現 。 若是您願意,請添加您的解決方案:) ui
您是否故意忽略了O,0和i? this
我剛剛基於Ryan的解決方案建立了一個PHP類。
<?php $shorty = new App_Shorty(); echo 'ID: ' . 1000; echo '<br/> Short link: ' . $shorty->encode(1000); echo '<br/> Decoded Short Link: ' . $shorty->decode($shorty->encode(1000)); /** * A nice shorting class based on Ryan Charmley's suggestion see the link on Stack Overflow below. * @author Svetoslav Marinov (Slavi) | http://WebWeb.ca * @see http://stackoverflow.com/questions/742013/how-to-code-a-url-shortener/10386945#10386945 */ class App_Shorty { /** * Explicitly omitted: i, o, 1, 0 because they are confusing. Also use only lowercase ... as * dictating this over the phone might be tough. * @var string */ private $dictionary = "abcdfghjklmnpqrstvwxyz23456789"; private $dictionary_array = array(); public function __construct() { $this->dictionary_array = str_split($this->dictionary); } /** * Gets ID and converts it into a string. * @param int $id */ public function encode($id) { $str_id = ''; $base = count($this->dictionary_array); while ($id > 0) { $rem = $id % $base; $id = ($id - $rem) / $base; $str_id .= $this->dictionary_array[$rem]; } return $str_id; } /** * Converts /abc into an integer ID * @param string * @return int $id */ public function decode($str_id) { $id = 0; $id_ar = str_split($str_id); $base = count($this->dictionary_array); for ($i = count($id_ar); $i > 0; $i--) { $id += array_search($id_ar[$i - 1], $this->dictionary_array) * pow($base, $i - 1); } return $id; } } ?>
public class UrlShortener { private static final String ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; private static final int BASE = ALPHABET.length(); public static String encode(int num) { StringBuilder sb = new StringBuilder(); while ( num > 0 ) { sb.append( ALPHABET.charAt( num % BASE ) ); num /= BASE; } return sb.reverse().toString(); } public static int decode(String str) { int num = 0; for ( int i = 0; i < str.length(); i++ ) num = num * BASE + ALPHABET.indexOf(str.charAt(i)); return num; } }
C#版本:
public class UrlShortener { private static String ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; private static int BASE = 62; public static String encode(int num) { StringBuilder sb = new StringBuilder(); while ( num > 0 ) { sb.Append( ALPHABET[( num % BASE )] ); num /= BASE; } StringBuilder builder = new StringBuilder(); for (int i = sb.Length - 1; i >= 0; i--) { builder.Append(sb[i]); } return builder.ToString(); } public static int decode(String str) { int num = 0; for ( int i = 0, len = str.Length; i < len; i++ ) { num = num * BASE + ALPHABET.IndexOf( str[(i)] ); } return num; } }
alphabet = map(chr, range(97,123)+range(65,91)) + map(str,range(0,10)) def lookup(k, a=alphabet): if type(k) == int: return a[k] elif type(k) == str: return a.index(k) def encode(i, a=alphabet): '''Takes an integer and returns it in the given base with mappings for upper/lower case letters and numbers 0-9.''' try: i = int(i) except Exception: raise TypeError("Input must be an integer.") def incode(i=i, p=1, a=a): # Here to protect p. if i <= 61: return lookup(i) else: pval = pow(62,p) nval = i/pval remainder = i % pval if nval <= 61: return lookup(nval) + incode(i % pval) else: return incode(i, p+1) return incode() def decode(s, a=alphabet): '''Takes a base 62 string in our alphabet and returns it in base10.''' try: s = str(s) except Exception: raise TypeError("Input must be a string.") return sum([lookup(i) * pow(62,p) for p,i in enumerate(list(reversed(s)))])a
這是我須要的版本。
我有一個問題的變體,由於我存儲了許多不一樣做者的網頁,而且須要防止經過猜想發現網頁。 所以,個人短網址在頁碼的Base-62字符串中添加了幾個額外的數字。 這些額外的數字是從頁面記錄自己的信息中生成的,它們確保3844個URL中只有1個有效(假定2個數字爲Base-62)。 您能夠在http://mgscan.com/MBWL上看到概述說明。