Ricerca di una funzione hash non crittografica che restituisca un singolo carattere

1

Supponiamo di avere un dizionario di parole ASCII memorizzato in maiuscolo. Voglio anche salvare quelle parole in file separati in modo che il numero totale di parole di ciascun file sia approssimativamente lo stesso. Semplicemente guardando la parola ho bisogno di sapere in quale file dovrebbe essere (se è lì). Le parole duplicate dovrebbero andare nello stesso file e sovrascrivere l'ultimo.

Il mio primo tentativo di risolvere questo problema è utilizzare la funzione object.GetHashCode() di .NET e .Trim() per ottenere uno dei caratteri "casuali" che appaiono. Ho fatto una domanda simile qui

Se utilizzo solo un carattere di object.GetHashCode() otterrei un carattere di codice hash di A..Z o 0..9. Tuttavia, il salvataggio del risultato di GetHashCode su disco è un no-no, quindi ho bisogno di un sostituto.

Domanda:

Che algoritmo (o sottoinsieme di un algoritmo ) è appropriato per il pigeonholing strings in un singolo carattere o intervallo di caratteri (come hex 0..F offre 16 caratteri)?

Utilizzo del mondo reale:

Userò questa risposta per modificare la chiave Partition utilizzata nell'archivio di Azure Table come descritto qui

    
posta random65537 20.11.2012 - 22:47
fonte

2 risposte

4

La funzione 'hash' più semplice sarebbe quella di prendere il primo carattere della stringa e quello è il codice hash. Funziona. Non ha una buona distribuzione, ma funziona per un certo grado di "lavoro".

Per ottenere un hash migliore, sommare il valore della stringa (A = 1, B = 2, C = 3 ...) e quindi prendere il modulo del valore risultante. Se questo deve essere assegnato all'intervallo di hash 'A-Z', prendi questo mod 26 e assegnalo nuovamente all'array di caratteri (in questo caso, A = 0). Se questo deve essere nel range hash esadecimale, prendi il valore mod 16.

    
risposta data 20.11.2012 - 22:55
fonte
1

Sembra che la tua domanda sia molto correlata al precedente stackoverflow domanda.

Generally speaking, Azure Table IO performance improves as more partitions are used (with some tradeoffs in continuation tokens and batch updates I won't go into).

Since the partition key is always a string I am considering using a "natural" load balancing technique based on a subset of the GetHashCode() of the partition key, and appending this subset to the partition key itself. This will allow all direct PK/RK queries to be computed with little overhead and with ease. Batch updates may just need an intermediate to group similar PKs together prior to submission

Con queste informazioni di base il problema non è semplicemente prendere un database di parole e dividerlo in più database di dimensioni minori, ma uguali, con le stesse parole. Sembra invece che tu stia cercando di determinare come suddividere automaticamente i tuoi dati in base a una chiave in modo che sia separata in parti uguali.

Se il nostro obiettivo finale è di suddividere le parole in modo uniforme tra i frammenti, non lo farei basandomi sui dati stessi. Vale a dire se il mio metodo per determinare in quale partizione un bit di dati è basato su ciò che è incluso in quei dati, non mi aspetto che la mia distribuzione finale sia pari.

Dato il seguente elenco di parole come un esempio

Programmer,Programmer,StackExchange

Il valore Programmer viene ripetuto due volte. Se quel valore è quello che sto usando per determinare in quale partizione i dati finiranno, mi aspetterei che entrambi i Programmatori finiscano nella stessa partizione. Se l'obiettivo finale è quello di mantenere tutte le parole strettamente correlate sulla stessa partizione, questo potrebbe essere il modo in cui vuoi andare, ma non credo che lo sia.

Se invece non ci importa quali siano le parole e voglia una distribuzione uniforme, dovrei prima determinare il numero di frammenti che voglio eseguire e quindi semplicemente scorrere il mio database di parole assegnando la chiave di partizione 1-N dove N è il numero di partizioni che ho.

cioè.

int totalPartitions = 5;
int currentPartition = 1;
Foreach(var item in MyData) {
  MyData.PartitionKey = currentPartition;
  if(currentPartition < totalPartitions)
    currentPartition++
  else
    currentPartition = 1;
}
    
risposta data 20.11.2012 - 23:16
fonte

Leggi altre domande sui tag