Каковы варианты создания удобных для пользователя буквенно-цифровых идентификаторов (например, business id, SKU)

StackOverflow https://stackoverflow.com/questions/217253

  •  03-07-2019
  •  | 
  •  

Вопрос

Вот требования:

Должен быть буквенно-цифровым, 8-10 символов, чтобы он был удобен для пользователя.Они будут сохранены в базе данных в виде уникальных ключей.Я использую Guid в качестве первичных ключей, поэтому было бы предпочтительнее использовать GUID для генерации этих уникальных идентификаторов.

Я думаю о строках конвертера base-n, который принимает Guid и преобразует в 8-символьную уникальную строку.

Предпочтителен короткий, легковесный алгоритм, поскольку он будет вызываться довольно часто.

Это было полезно?

Решение

Вы можете рассмотреть базу 36. в том, что она может выполнять буквы и цифры. Подумайте об удалении I (глаз) и O (О) из вашего набора, чтобы они не смешивались с 1 (один) и 0 (ноль). Некоторые люди могут также жаловаться на 2 и Z.

Другие советы

8 characters - perfectly random - 36^8 = 2,821,109,907,456 combinations
10 characters - perfectly random - 36^10 = 3,656,158,440,062,976 combinations
GUID's - statistically unique* - 2^128 = 340,000,000,000,000,000,000,000,000,000,000,000,000 combinations

* Является ли GUID уникальным в 100% случаев?[stackoverflow] [стековый поток]

Проблема с вашим GUID -> преобразованием символов;хотя ваш GUID статистически уникален, беря любое подмножество, вы уменьшаете случайность и увеличиваете вероятность столкновений.Вы, конечно же, не хотите создавать нестандартные артикулы.


Решение 1:

Создайте артикул, используя данные, относящиеся к объекту, и бизнес-правила.

т. е.Вероятно, существует небольшая комбинация атрибутов, которая делает объект уникальным (естественный ключ).Объедините элементы естественного ключа, закодируйте и сожмите их, чтобы создать артикул.Часто все, что вам нужно, - это поле даты и времени (т. Е. CreationDate) и несколько других свойств для достижения этой цели.Вероятно, у вас будет много пробелов в создании артикулов, но артикулы более актуальны для ваших пользователей.

гипотетически:

Wholesaler, product name, product version, sku
Amazon,     IPod Nano,    2.2,             AMIPDNN22
BestBuy,    Vaio,         3.2,             BEVAIO32

Решение 2:

Метод, который резервирует диапазон чисел, а затем последовательно освобождает их и никогда не возвращает одно и то же число дважды.У вас все еще могут получиться дыры в ассортименте.Скорее всего, вам не нужно генерировать достаточное количество артикулов, чтобы это имело значение, но убедитесь, что ваши требования позволяют это сделать.

Реализация должна иметь key таблица в базе данных, у которой есть счетчик.Счетчик увеличивается в транзакции.Важным моментом является то, что вместо увеличения на 1 программный метод захватывает блок.псевдо-c#-код выглядит следующим образом.

-- what the key table may look like
CREATE TABLE Keys(Name VARCHAR(10) primary key, NextID INT)
INSERT INTO Keys Values('sku',1)

// some elements of the class
public static SkuKeyGenerator 
{
    private static syncObject = new object();
    private static int nextID = 0;
    private static int maxID = 0;
    private const int amountToReserve = 100;

    public static int NextKey()
    {
        lock( syncObject )
        {
            if( nextID == maxID )
            {
                ReserveIds();
            }
            return nextID++;
        }
    }
    private static void ReserveIds()
    {
        // pseudocode - in reality I'd do this with a stored procedure inside a transaction,
        // We reserve some predefined number of keys from Keys where Name = 'sku'
        // need to run the select and update in the same transaction because this isn't the only
        // method that can use this table.
        using( Transaction trans = new Transaction() ) // pseudocode.
        {
             int currentTableValue = db.Execute(trans, "SELECT NextID FROM Keys WHERE Name = 'sku'");
             int newMaxID = currentTableValue + amountToReserve;
             db.Execute(trans, "UPDATE Keys SET NextID = @1 WHERE Name = 'sku'", newMaxID);

             trans.Commit();

             nextID = currentTableValue;
             maxID = newMaxID;
        }
    } 

Идея здесь в том, что вы резервируете достаточное количество ключей, чтобы ваш код не попадал часто в базу данных, поскольку получение диапазона ключей является дорогостоящей операцией.Вы должны иметь хорошее представление о количестве ключей, которые вам нужно зарезервировать, чтобы сбалансировать потерю ключа (перезапуск приложения) и слишком быстрое исчерпание ключей и возврат к базе данных.Эта простая реализация не имеет возможности повторно использовать потерянные ключи.

Поскольку эта реализация опирается на базу данных и транзакции, вы можете запускать приложения одновременно, и все они генерируют уникальные ключи без необходимости часто обращаться к базе данных.

Обратите внимание, что вышесказанное в общих чертах основано на key table, страница 222 из Шаблоны архитектуры корпоративных приложений (Фаулер).Этот метод обычно используется для генерации первичных ключей без использования столбца идентификатора базы данных, но вы можете увидеть, как его можно адаптировать для ваших целей.

Если вы ищете " дружественный пользователю " Возможно, вы захотите использовать целые слова вместо того, чтобы просто сделать их короткими / буквенно-цифровыми, таким образом, что-то вроде:

words = [s.strip().lower() for s in open('/usr/share/dict/canadian-english') if "'" not in s]
mod = len(words)

def main(script, guid):
    guid = hash(guid)

    print "+".join(words[(guid ** e) % mod] for e in (53, 61, 71))

if __name__ == "__main__":
    import sys
    main(*sys.argv)

Который производит вывод вроде:

oranjestad+compressing+wellspring
padlock+discommoded+blazons
pt+olenek+renews

Что забавно. В противном случае, лучше всего взять первые 8-10 символов guid или sha1 / md5 хеша guid.

Самое простое, что может сработать, - это счетчик, который увеличивается каждый раз, когда требуется значение. Восемь (слева от нуля) цифр дает вам 100 миллионов возможных значений от 00000000 до 99999999 (хотя вы можете вставлять пробелы или дефисы для удобства чтения, как в 000-000-00).

Если вам потребуется более 100 миллионов значений, вы можете либо увеличить длину, либо использовать буквы в альтернативных позициях. Использование A0A0A0A0 через Z9Z9Z9Z9 дает вам более четырех с половиной миллиардов возможных значений (4 569 760 000). Это тривиальный бит кода для получения длинного целого числа и создания такой кодировки (мод 10 для самой правой цифры, деление на 10, затем мод 26 для самой правой буквы и т. Д.) Если у вас есть память для записи, самый быстрый способ заключается в преобразовании счетчика в массив mod 260 и использовании каждого значения mod 260 в качестве индекса в массив двухсимвольных строк («A0», «A1», «A2» и т. д. через »). A9 "," B0 "," B1 "и т. Д. До" Z9 ").

Проблема с базой 36 (упомянутая в другом ответе) заключается в том, что вам нужно не только беспокоиться о путанице читателя с похожими символами (один против I, ноль против O, два против Z, пять против S), но и также о сочетаниях смежных букв, которые читатели могут воспринимать как написание неприятных или нецензурных слов или сокращений.

Вы можете попробовать алгоритм хэширования CRC32. CRC32 генерирует строку из 8 символов.

http://en.wikipedia.org/wiki/Cyclic_redundancy_check

http://textop.us/Hashing/CRC

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top