2009-06-30 36 views
2

我正在创建一个由各种用户执行的一些测试结果的文件导向数据库。为此,我需要为数据库中的每个条目生成唯一的ID。的ID必须满足下列要求:如何在Perl中创建唯一标识符?

  • IDS应该是相当小的(至多6个字符)
  • 对于每个测试实例,并且每个时间相同的id应生成

我尝试什么用户组合是一个简单的BKDR散列函数与种子值31和用ORD()函数,如下所示:

@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" ; 

这有时会导致同样的结果为各种组合,即ù没有观察到独特性。他们有什么其他的方式来完成这个吗?改变种子价值是否有助于实现独特性?

回答

3

你的问题的一部分可能是你正在使用浮点数学和BKDR几乎肯定是想整数数学。你可以通过说

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

另一个调整可能会帮助使用除第一个和最后一个字符以外的其他调整。如果第一个和最后一个字符倾向于相同,那么它们不会为该散列添加唯一性。

您可能还想使用更好的散列函数,如MD5(可在Digest :: MD5中找到)并将结果修剪为所需的大小。但是,您使用散列的事实意味着您有发生碰撞的风险。

5

您是否有超过256个用户和/或超过65536个测试用例?如果没有,你可以索引0 .. 255的用户和0 .. 65535的测试用例,并将其编码为一串十六进制数字,这样就可以有六个字符。

如果你有更多的用户或测试用例,我会再次索引用户和测试用例,然后将它们合并成一个32位整数,实际上只需要4个字节并且实现起来微不足道,但稍微难一点人类。

无论如何,我假设你给出了用户名和测试用例信息。只需保留两个并列散列:%users%cases即可将用户和测试用例映射到其索引编号。

1

如果你没有很多的用户/测试用例,这样一个简单的解决方案可能就足够了。您必须添加限制(并且在存储时可能会打包整数)。

[email protected]:~# 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"; 
     } 
} 
[email protected]:~# 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 
+1

你认为你究竟是从这个原型中走出来的?在使用另一个链接之前,您可能需要阅读以下链接:http://www.perl.com/language/misc/fmproto.html – 2009-06-30 12:57:25

+0

混合语言的问题。我编写了getUniqueId(),然后决定修复原型而不是删除它。 – 2009-06-30 13:41:20