¿Cuáles son las opciones para generar ID alfanuméricos fáciles de usar (como ID de empresa, SKU)?

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

  •  03-07-2019
  •  | 
  •  

Pregunta

Aquí están los requisitos:

Debe ser alfanumérico, de 8 a 10 caracteres para que sea fácil de usar. Estos serán almacenados como claves únicas en la base de datos. Estoy usando Guids como claves principales, por lo que sería preferible una opción para usar GUids para generar estos Id. Únicos.

Estoy pensando en las líneas de un convertidor de base-n que toma un Guid y se convierte en una cadena única de 8 caracteres.

Se prefiere un algoritmo corto y liviano, ya que se llamaría con bastante frecuencia.

¿Fue útil?

Solución

Puede considerar base 36. porque puede hacer letras y números. Considere eliminar I (ojo) y O (Oh) de su conjunto para que no se mezclen con 1 (uno) y 0 (cero). Algunas personas pueden quejarse de 2 y Z también.

Otros consejos

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

* ¿Es un GUID único el 100% del tiempo? [stackoverflow]

El problema con su GUID - > conversión de caracteres; Si bien su GUID es estadísticamente único, al tomar cualquier subconjunto, disminuye la aleatoriedad y aumenta la posibilidad de colisiones. Ciertamente no quieres crear SKU que no sean unqiue.


Solución 1:

Cree el código de artículo utilizando los datos relevantes para el objeto y las reglas empresariales.

es decir, Es probable que haya una pequeña combinación de atributos que hace que un objeto sea único (una clave natural) . Combine los elementos de la clave natural, codifíquelos y comprímalos para crear un SKU. A menudo, todo lo que necesita es un campo de fecha y hora (es decir, CreationDate) y algunas otras propiedades para lograrlo. Es probable que tengas muchos agujeros en la creación de sku, pero los sku son más relevantes para tus usuarios.

hipotéticamente:

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

Solución 2:

Un método que reserva un rango de números y luego los libera secuencialmente, y nunca devuelve el mismo número dos veces. Todavía puede terminar con agujeros en el rango. Aunque es probable que no necesite generar suficientes sku para importar, pero asegúrese de que sus requisitos lo permitan.

Una implementación es tener una tabla key en una base de datos que tiene un contador. El contador se incrementa en una transacción. Un punto importante es que, en lugar de aumentar en 1, el método en software toma un bloque. el pseudo-c # -code es el siguiente.

-- 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;
        }
    } 

La idea aquí es que reserve suficientes claves para que su código no vaya a la base de datos con frecuencia, ya que obtener el rango de claves es una operación costosa. Debe tener una buena idea de la cantidad de claves que necesita reservar para equilibrar la pérdida de claves (reinicio de la aplicación) en lugar de agotar las claves demasiado rápido y volver a la base de datos. Esta implementación simple no tiene manera de reutilizar las claves perdidas.

Debido a que esta implementación se basa en una base de datos y transacciones, puede tener aplicaciones ejecutándose simultáneamente y todas generan claves únicas sin necesidad de ir a la base de datos con frecuencia.

Tenga en cuenta que lo anterior se basa libremente en key table , página 222 de Patterns de Enterprise Application Architecture (Fowler) . El método generalmente se usa para generar claves primarias sin la necesidad de una columna de identidad de base de datos, pero puede ver cómo puede adaptarse para su propósito.

Si buscas " usuario amigable " es posible que desee probar el uso de palabras completas en lugar de simplemente hacerlo corto / alfanumérico, por lo tanto, algo como:

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)

Lo que produce una salida como:

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

Que es divertido. De lo contrario, la mejor opción es tomar los primeros 8-10 caracteres del guid o el hash sha1 / md5 del guid.

Lo más simple que podría funcionar es un contador que se incrementa cada vez que se requiere un valor. Ocho dígitos (izquierdo-rellenado) le dan 100 millones de valores posibles de 00000000 a 99999999 (aunque podría intercalar espacios o guiones para facilitar la lectura humana, como en 000-000-00).

Si necesita más de 100 millones de valores, puede aumentar la longitud o usar letras en posiciones alternativas. El uso de A0A0A0A0 a través de Z9Z9Z9Z9 le brinda más de cuatro mil quinientos valores posibles (4,569,760,000) disponibles. Es un bit trivial de código para tomar un entero largo y producir tal codificación (mod 10 para el dígito más a la derecha, div por 10 y luego mod 26 para la letra más a la derecha, etc.) Si tiene la memoria para grabar, la forma más rápida es convertir el contador a una matriz mod 260, y usar cada valor mod 260 como un índice en una matriz de cadenas de dos caracteres ("A0", "A1", "A2", y así sucesivamente a través de " A9 ", " B0 " ;, " B1 " ;, etc. a través de " Z9 ").

El problema con la base 36 (mencionado en otra respuesta) es que no solo tiene que preocuparse por la confusión del lector con caracteres similares (uno contra I, cero contra O, dos contra Z, cinco contra S) sino también sobre combinaciones de letras adyacentes que pueden ser percibidas por los lectores como palabras o abreviaturas de mal gusto u obscenas.

Es posible que desee probar un algoritmo de hashing CRC32. El CRC32 genera una cadena de 8 caracteres.

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

http://textop.us/Hashing/CRC

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top