Quali sono le opzioni per generare ID alfanumerici facili da usare (come ID commerciale, SKU)

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

  •  03-07-2019
  •  | 
  •  

Domanda

Ecco i requisiti:

Deve essere alfanumerico, 8-10 caratteri, in modo che sia facile da usare. Questi verranno memorizzati come chiavi univoche nel database. Sto usando le guide come chiavi primarie, quindi sarebbe preferibile un'opzione per usare le guide per generare questi ID univoci.

Sto pensando alle linee di un convertitore base-n che prende un Guid e si converte in una stringa univoca di 8 caratteri.

Algoritmo breve e leggero preferito come verrebbe chiamato abbastanza spesso.

È stato utile?

Soluzione

Potresti considerare base 36. in quanto può fare lettere e numeri. Prendi in considerazione la rimozione di I (occhio) e O (Oh) dal tuo set in modo che non si confondano con 1 (uno) e 0 (zero). Alcune persone potrebbero anche lamentarsi di 2 e Z.

Altri suggerimenti

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

* Un GUID è unico al 100% delle volte? [StackOverflow]

Il problema con il tuo GUID - > conversione del personaggio; mentre il tuo GUID è statisticamente unico, prendendo qualsiasi sottoinsieme diminuisci la casualità e aumenti la possibilità di collisioni. Non vorrai certo creare SKU non unqiue.


Soluzione 1:

Crea SKU usando i dati rilevanti per l'oggetto e le regole di business.

vale a dire. È probabile che ci sia una piccola combinazione di attributi che rende un oggetto unico (una chiave naturale) . Combina gli elementi della chiave naturale, codificali e comprimi per creare uno SKU. Spesso tutto ciò che serve è un campo data-ora (cioè CreationDate) e alcune altre proprietà per raggiungere questo obiettivo. Probabilmente avrai molti buchi nella creazione di sku, ma gli sku sono più rilevanti per i tuoi utenti.

ipoteticamente:

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

Soluzione 2:

Un metodo che riserva un intervallo di numeri, quindi procede al loro rilascio sequenziale e non restituisce mai lo stesso numero due volte. Puoi ancora finire con buchi nell'intervallo. Probabilmente non è necessario generare abbastanza sku per importare, ma assicurarsi che i requisiti lo consentano.

Un'implementazione deve avere una tabella chiave in un database che ha un contatore. Il contatore viene incrementato in una transazione. Un punto importante è che, anziché incrementare di 1, il metodo nel software prende un blocco. pseudo-c # -code è il seguente.

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

L'idea qui è che riservi abbastanza chiavi in ??modo che il tuo codice non vada spesso nel database, poiché ottenere l'intervallo di chiavi è un'operazione costosa. È necessario avere una buona idea del numero di chiavi che è necessario prenotare per bilanciare la perdita delle chiavi (riavvio dell'applicazione) rispetto all'esaurimento delle chiavi troppo rapidamente e tornare al database. Questa semplice implementazione non ha modo di riutilizzare le chiavi perse.

Poiché questa implementazione si basa su un database e sulle transazioni, è possibile che le applicazioni vengano eseguite contemporaneamente e tutte generino chiavi univoche senza la necessità di accedere spesso al database.

Si noti che quanto sopra è vagamente basato sulla tabella delle chiavi , pagina 222 da Patterns di Enterprise Application Architecture (Fowler) . Il metodo viene generalmente utilizzato per generare chiavi primarie senza la necessità di una colonna di identità del database, ma puoi vedere come può essere adattato per il tuo scopo.

Se stai cercando " user friendly " potresti voler provare a usare parole intere anziché semplicemente renderle brevi / alfanumeriche, quindi qualcosa del tipo:

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)

Che produce output come:

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

Che è divertente. Altrimenti, prendere semplicemente i primi 8-10 caratteri del guid o l'hash sha1 / md5 del guid è probabilmente la soluzione migliore.

La cosa più semplice che potrebbe funzionare è un contatore che viene incrementato ogni volta che è richiesto un valore. Otto cifre (con spaziatura zero a zero) forniscono 100 milioni di possibili valori da 00000000 a 99999999 (sebbene sia possibile intercettare spazi o trattini per la leggibilità umana, come in 000-000-00).

Se avrai bisogno di oltre 100 milioni di valori, puoi aumentare la lunghezza o usare le lettere in posizioni alternative. L'uso di A0A0A0A0 tramite Z9Z9Z9Z9 offre oltre quattro miliardi e mezzo di valori possibili (4.569.760.000) disponibili. È un banale bit di codice prendere un intero lungo e produrre una tale codifica (mod 10 per la cifra più a destra, div per 10 quindi mod 26 per la lettera più a destra, ecc.) Se hai la memoria da masterizzare, il modo più veloce consiste nel convertire il contatore in un array mod 260 e utilizzare ciascun valore mod 260 come indice in un array di stringhe di due caratteri ("A0", "A1", "A2", e così via attraverso " A9 "," B0 "," B1 ", ecc. Attraverso" Z9 ").

Il problema con la base 36 (menzionato in un'altra risposta) è che non devi solo preoccuparti della confusione del lettore di caratteri simili (uno contro I, zero contro O, due contro Z, cinque contro S) ma anche sulle combinazioni di lettere adiacenti che potrebbero essere percepite dai lettori come ortografia di parole o abbreviazioni sgradevoli o oscene.

Potresti provare un algoritmo di hashing CRC32. Il CRC32 genera una stringa di 8 caratteri.

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

http://textop.us/Hashing/CRC

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top