如果有一个长 URL,我想生成一个短 URL,就像 Twitter 中的那样。有没有办法在 Ruby 中实现这一点?
最佳答案
最简单的方法是:
- 保存所有网址的数据库
- 在向数据库中插入新 URL 时,找出自增整数主键的 id。
- 将该整数编码为基数 36 或 62(数字 + 小写字母或数字 + 混合大小写字母)。瞧!你有一个短网址!
在 Ruby 中编码到 base 36/从 base 36 解码很简单:
12341235.to_s(36)
#=> "7cik3"
"7cik3".to_i(36)
#=> 12341235
编码为 base 62 有点复杂。这是一种方法:
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
...它正在发挥作用:
base36 = "0123456789abcdefghijklmnopqrstuvwxyz"
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
编辑
如果您想避免恰好是英文单词的 URL(例如,四个字母的脏话),您可以使用一组不包含元音的字符:
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
但是,您仍然会遇到 AnyBase.encode(328059,base31)
或 AnyBase.encode(345055,base31)
或 AnyBase.encode 等问题(450324,base31)
。因此,您可能还想避免类似元音的数字:
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
这也将避免“是 0 还是 O?”的问题。和“那是 1 还是 I?”。
关于ruby - 如何实现类似于 Twitter 中的 URL 的短 URL?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6338870/