Вместо этого используйте const_iterator
. iterator
допускает модификацию vector
, поэтому вы не можете получить его из контейнера const
.
Кроме того, идиоматический способ записи этого цикла использует it != students.end()
вместо <
] (хотя это должно работать на vector
).
I would continue your "convert number to string" approach. However, you will realize that your proposed algorithm fails if your ID is a prime and greater than 52.
You need a Bijective Function f. This is necessary so that you can find a inverse function g('abc') = 123 for your f(123) = 'abc' function. This means:
[a-zA-Z0-9]
. It contains 62 letters.Take an auto-generated, unique numerical key (the auto-incremented id
of a MySQL table for example).
For this example, I will use 12510 (125 with a base of 10).
Now you have to convert 12510 to X62 (base 62).
12510 = 2×621 + 1×620 = [2,1]
This requires the use of integer division and modulo. A pseudo-code example:
digits = []
while num > 0
remainder = modulo(num, 62)
digits.push(remainder)
num = divide(num, 62)
digits = digits.reverse
Now map the indices 2 and 1 to your alphabet. This is how your mapping (with an array for example) could look like:
0 → a
1 → b
...
25 → z
...
52 → 0
61 → 9
With 2 → c and 1 → b, you will receive cb62 as the shortened URL.
http://shor.ty/cb
Обратное еще проще. Вы просто делаете обратный поиск в вашем алфавите.
e9a 62 будут преобразованы в «4-ю, 61-ю и 0-ю букву в алфавите».
e9a 62 = [4,61,0]
= 4 × 62 2 + 61 × 62 1 + 0 × 62 0 = 19158 10
Теперь найдите вашу запись базы данных с WHERE id = 19158
и выполните перенаправление.
Качественное решение Node.js / JavaScript см. В модуле id-shorttener , который тщательно протестирован и уже несколько месяцев используется в производстве.
Он обеспечивает эффективное сокращение идентификатора / URL-адреса при поддержке сменного хранилища по умолчанию Redis , и вы даже можете настроить свой короткий набор символов идентификатора и определить, является ли сокращение идемпотентным . Это важное различие, которое учитывают не все сокращатели URL-адресов.
В отношении других ответов здесь, этот модуль реализует превосходный принятый ответ Марселя Джекверта выше.
В основе решения лежит следующий фрагмент Redis Lua :
local sequence = redis.call('incr', KEYS[1])
local chars = '0123456789ABCDEFGHJKLMNPQRSTUVWXYZ_abcdefghijkmnopqrstuvwxyz'
local remaining = sequence
local slug = ''
while (remaining > 0) do
local d = (remaining % 60)
local character = string.sub(chars, d + 1, d + 1)
slug = character .. slug
remaining = (remaining - d) / 60
end
redis.call('hset', KEYS[2], slug, ARGV[1])
return slug
Для аналогичного проекта, чтобы получить новый ключ, я создаю функцию-обертку вокруг генератора случайных строк , который вызывает генератор, пока не получу строку, которая еще не использовалась в моей хеш-таблице. Этот метод замедляется, как только ваше пространство имен начинает заполняться, но, как вы сказали, даже с 6 символами у вас есть достаточно пространства имен для работы.
Почему бы просто не перевести свой идентификатор в строку? Вам просто нужна функция, которая отображает цифру, скажем, от 0 до 61, в одну букву (верхний / нижний регистр) или цифру. Затем примените это для создания, скажем, четырехбуквенных кодов, и вы получите 14,7 миллионов URL-адресов.
Если вы не хотите повторно -изобрести колесо ... http://lilurl.sourceforge.net/
Мой подход: взять идентификатор базы данных, затем Base36 кодировать его . Я бы НЕ использовал как заглавные, так и строчные буквы, потому что это делает передачу этих URL-адресов по телефону кошмаром, но вы, конечно, легко могли бы расширить эту функцию до базового 62 en / decoder.
Не ответ на ваш вопрос, но я бы не стал использовать сокращенные URL-адреса с учетом регистра. Их трудно запомнить, как правило, нечитаемые (многие шрифты отображают 1 и l, 0 и O и другие символы очень похожи, так что почти невозможно различить их) и подвержены прямым ошибкам. Попробуйте использовать только нижний или верхний регистр.
Кроме того, попробуйте использовать формат, в котором вы смешиваете цифры и символы в предварительно определенной форме. Существуют исследования, которые показывают, что люди, как правило, запоминают одну форму лучше, чем другие (например, номера телефонов, где номера сгруппированы в определенной форме). Попробуйте что-то вроде num-char-char-num-char-char. Я знаю, что это уменьшит комбинации, особенно если у вас нет прописных и строчных букв, но это было бы более удобно и поэтому полезно.
Зачем вам использовать хеш?
Вы можете просто использовать простой перевод значения автоинкремента в буквенно-цифровое значение. Вы можете сделать это легко с помощью некоторого базового преобразования. Допустим, у вас есть место для символов (AZ, az, 0-9 и т. Д.), Состоящее из 40 символов, преобразуйте идентификатор в число с основанием 40 и используйте символы в качестве цифр.
Почему не только генерируют случайную строку и добавляют его к базовому URL? Это - очень упрощенная версия выполнения этого в C#.
static string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
static string baseUrl = "https://google.com/";
private static string RandomString(int length)
{
char[] s = new char[length];
Random rnd = new Random();
for (int x = 0; x < length; x++)
{
s[x] = chars[rnd.Next(chars.Length)];
}
Thread.Sleep(10);
return new String(s);
}
Затем просто добавляют добавление случайной строки к baseURL:
string tinyURL = baseUrl + RandomString(5);
Помнят, что это - очень упрощенная версия выполнения этого, и возможно, что метод RandomString мог создать дублирующиеся строки. В производстве Вы хотели бы взять в счете на дублирующиеся строки, чтобы гарантировать, что у Вас всегда будет уникальный URL. у меня есть некоторый код, который принимает во внимание для дублирующихся строк путем запросов таблицы базы данных, которую я мог совместно использовать, если кому-либо интересно.
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
Here's my version for whomever needs it.