2011-06-14 13 views

Respuesta

59

La forma más sencilla es:

  1. mantener una base de datos de todas las URL
  2. cuando se inserta un nuevo URL en la base de datos, busque el ID de la clave primaria número entero de incremento automático.
  3. codifique ese número entero en la base 36 o 62 (dígitos + letras minúsculas o dígitos + alfa de mayúsculas y minúsculas). Voila! ¡Tienes una url corta!

Encoding a la base 36/decodificación de la base 36 es simple en Ruby:

12341235.to_s(36) 
#=> "7cik3" 

"7cik3".to_i(36) 
#=> 12341235 

Encoding a la base 62 es un Tricker poco. He aquí una manera de hacerlo:

module AnyBase 
    ENCODER = Hash.new do |h,k| 
    h[k] = Hash[ k.chars.map.with_index.to_a.map(&:reverse) ] 
    end 
    DECODER = Hash.new do |h,k| 
    h[k] = Hash[ k.chars.map.with_index.to_a ] 
    end 
    def self.encode(value, keys) 
    ring = ENCODER[keys] 
    base = keys.length 
    result = [] 
    until value == 0 
     result << ring[ value % base ] 
     value /= base 
    end 
    result.reverse.join 
    end 
    def self.decode(string, keys) 
    ring = DECODER[keys] 
    base = keys.length 
    string.reverse.chars.with_index.inject(0) do |sum,(char,i)| 
     sum + ring[char] * base**i 
    end 
    end 
end 

... y aquí está en acción:

base36 = "abcdefghijklmnopqrstuvwxyz" 
db_id = 12341235 
p AnyBase.encode(db_id, base36) 
#=> "7cik3" 
p AnyBase.decode("7cik3", base36) 
#=> 12341235 

base62 = [ *0..9, *'a'..'z', *'A'..'Z' ].join 
p AnyBase.encode(db_id, base62) 
#=> "PMwb" 
p AnyBase.decode("PMwb", base62) 
#=> 12341235 

Editar

Si quieres evitar las URL que pasan a ser las palabras inglesas (por ejemplo, groserías de cuatro letras) puede usar un conjunto de caracteres que no incluye las vocales:

base31 = ([*0..9,*'a'..'z'] - %w[a e i o u]).join 
base52 = ([*0..9,*'a'..'z',*'A'..'Z'] - %w[a e i o u A E I O U]).join 

Sin embargo, con esto todavía tiene problemas como AnyBase.encode(328059,base31) o AnyBase.encode(345055,base31) o AnyBase.encode(450324,base31). por tanto, es posible que desee evitar los números vocal-similares, así:

base28 = ([*'0'..'9',*'a'..'z'] - %w[a e i o u 0 1 3]).join 
base49 = ([*'0'..'9',*'a'..'z',*'A'..'Z'] - %w[a e i o u A E I O U 0 1 3]).join 

Esto también evitará el problema de "¿Es eso un 0 o un O?" y "¿Es eso un 1 o un I?".

+5

que me han ayudado por muchas veces, realmente aprecio su ayuda, la respuesta cada vez que usted ofrece es grande, muchas gracias mucho . – ywenbo

+1

Tenga cuidado con esta implementación, ya que generará palabras legibles que podría evitar. P.ej. 645860.to_s (36) = 'pato'. 739172 podría considerarse un poco peor. Recomiendo ir con base20 (0-9a-j) o similar. Para ayudar a decidir, incluso puede usar un buscador de anagramas como 'juegos de palabras', como por ejemplo: 'juego de palabras 'aaabbbcccdddeeefffggghhhiiijjj'' - le muestra qué palabras se pueden generar. – user569825

+0

@ user569825 Gracias por la nota (aunque esto parece una mala razón para votar negativamente). Sugeriría quizás un conjunto básico de caracteres sin vocales como una forma más simple y menos impactante. – Phrogz

1

Bueno, podrías generar URL cortas usando las API de tantos servicios de acortamiento de url. Casi todos los servicios que hay ofrecen una API para que puedas invocar y acortar las URL, así es exactamente como los clientes de Twitter también lo hacen. Debería consultar el sitio web del servicio de acortamiento de URL particular para obtener más detalles.

Si desea crear un servicio por su cuenta, eso también puede ser bastante simple, todo lo que necesita hacer es esencialmente mantener una asignación interna (en una base de datos) entre la url larga original y una URL corta especial (generado por ti). Y cuando recibe una solicitud de una url corta en particular, debe poder obtener la url larga original de la base de datos y redirigir al usuario a la misma.

11

Uso la gema bitly. Es realmente simple.

gem install bitly 

# Use api version 3 or get a deprecation warning 
Bitly.use_api_version_3 

# Create a client 
bitly = Bitly.new(username, api_key) 

# Call method shorten 
bitly.shorten('http://www.google.com').short_url 
1

para Ruby 2.0, reemplace el método de decodificación por:

def self.decode(string, keys) 
    ring = DECODER[keys] 
    base = keys.length 
    string.reverse.chars.map.with_index.inject(0) do |sum,(char,i)| 
    sum + ring[char] * base**i 
    end 
end 
Cuestiones relacionadas