Domanda

Sto creando un file-oriented database di alcuni risultati di test effettuati da vari utenti.Per questo ho bisogno di generare un id univoco per ogni voce nel database.L'id deve soddisfare i seguenti requisiti:

  • Id deve essere abbastanza piccolo (6 caratteri al massimo)
  • Per ogni caso di test e la combinazione dell'utente ogni volta che stesso id deve essere generato

Quello che ho provato era un semplice BKDR funzione di hash con valore di inizializzazione 31 e utilizzato funzione ord() come segue:

@chars = split(//,$hash_var);

$hash = 0;
$seed = 31;

foreach $char ( @chars ) {
   if( $char !~ m/\d/ ) {
       $hash = ( $seed * $hash ) + ord( $char );
   }  
   else {
       $hash = ( $seed * $hash ) + $char ;
   }
}

$hash = ( $hash & 0x7FFFFFFF ) % 1000;
$hash = "$chars[0]$chars[$#chars]$hash" ;

Questo a volte porta a risultati stessi per le diverse combinazioni che ho.e l'unicità non è osservata.È proprio nessun altro modo per ottenere questo risultato?Non cambiando il valore di inizializzazione aiutare a realizzare l'unicità.

È stato utile?

Soluzione

Parte del problema potrebbe essere che si sta utilizzando, matematica in virgola mobile e BKDR è quasi certamente volendo intero matematiche.È possibile risolvere il bug dicendo

my @chars = split(//,$hash_var);

my $hash = 0;
my $seed = 31;

for my $char ( @chars ) {
   use integer;
   if( $char !~ m/\d/ ) {
       $hash = ( $seed * $hash ) + ord( $char );
   }  
   else {
       $hash = ( $seed * $hash ) + $char ;
   }
}

$hash = ( $hash & 0x7FFFFFFF ) % 1000;
$hash = "$chars[0]$chars[$#chars]$hash" ;

Un altro tweak che potrebbe aiutare utilizza caratteri diversi da quelli del primo e dell'ultimo.Se il primo e l'ultimo caratteri tendono ad essere la stessa, che non aggiunge unicità di hash.

Si potrebbe anche voler utilizzare una migliore funzione di hash come MD5 (disponibile in Digest::MD5) e tagliare il risultato alla dimensione desiderata.Tuttavia, il fatto che si sta utilizzando un hash a tutti i mezzi che si corre il rischio di avere una collisione.

Altri suggerimenti

Hai più di 256 utenti e/o più di 65536 casi di test per utente?Se non, si può solo indice di utenti da 0 ..255 e i casi di test da 0 ..65535 e codificare una stringa di cifre esadecimali così sei personaggi andrebbe bene.

Se si dispone di più utenti o i casi di test, vi sarebbe ancora una volta indice di utenti e casi di test e poi unirli in un numero intero a 32 bit che sarebbe in realtà solo 4 byte e di essere banale da implementare, ma un po ' di più sugli esseri umani.

In ogni caso, sto supponendo che si sono date il nome utente e prova le informazioni del caso.Basta tenere due legati hash: %users e %cases per mappare gli utenti e casi di test relativi numeri di indice.

Se non si dispone di un sacco di utenti/testcases una soluzione semplice come questo potrebbe essere sufficiente.Dovete aggiungere il limite (e probabilmente pack intero quando conservarlo).

vinko@parrot:~# more hash.pl
use strict;
use warnings;

my %hash;
my $count = 0;

sub getUniqueId {

        my $_user = shift;
        my $_test = shift;
        my $val;

        my $key = $_user."|".$_test;
        if (defined $hash{$key}) {
                $val = $hash{$key};
        } else {
                $hash{$key} = $count;
                $val = $count;
                $count = $count + 1;
        }
        return $val;
}

my @users = qw{ user1 user2 user3 user4 user5 user3 user5 };
my @testcases = qw{ test1 test2 test3 test1 test1 };

for my $user (@users) {
        for my $test (@testcases) {
                print "$user $test: ".getUniqueId($user,$test)."\n";
        }
}
vinko@parrot:~# perl hash.pl
user1 test1: 0
user1 test2: 1
user1 test3: 2
user1 test1: 0
user1 test1: 0
user2 test1: 3
user2 test2: 4
user2 test3: 5
user2 test1: 3
user2 test1: 3
user3 test1: 6
user3 test2: 7
user3 test3: 8
user3 test1: 6
user3 test1: 6
user4 test1: 9
user4 test2: 10
user4 test3: 11
user4 test1: 9
user4 test1: 9
user5 test1: 12
user5 test2: 13
user5 test3: 14
user5 test1: 12
user5 test1: 12
user3 test1: 6
user3 test2: 7
user3 test3: 8
user3 test1: 6
user3 test1: 6
user5 test1: 12
user5 test2: 13
user5 test3: 14
user5 test1: 12
user5 test1: 12
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top