【发布时间】:2015-01-07 19:21:30
【问题描述】:
在 Perl 中,如果您有一个包含偶数个元素的列表,您可以直接将其转换为哈希:
my @a = qw(each peach pear plum);
my %h = @a;
但是,如果有重复的键,那么它们将被静默接受,最后一次出现的是使用的键。我想做一个哈希检查是否有重复:
my @a = qw(a x a y);
my %h = safe_hash_from_list(@a); # prints error: duplicate key 'a'
显然我可以自己编写该例程:
sub safe_hash_from_list {
die 'even sized list needed' if @_ % 2;
my %r;
while (@_) {
my $k = shift;
my $v = shift;
die "duplicate key '$k'" if exists $r{$k};
$r{$k} = $v;
}
return %r;
}
然而,这比简单的赋值要慢很多。此外,如果有一个 CPAN 模块已经完成相同的工作,我不想使用我自己的私有例程。
在 CPAN 上是否有合适的例程可以安全地将列表转换为哈希?理想情况下,它比上面的纯 Perl 实现快一点(尽管可能永远不会像简单的赋值那样快)。
如果允许我提出相关的后续问题,我还想知道一个绑定的哈希类,它允许每个键只分配一次并在重新分配时死亡。这将是上述问题的更一般情况。同样,我可以自己编写这样的绑定哈希,但我不想重新发明轮子,如果已经存在,我更喜欢优化的实现。
【问题讨论】:
-
是什么让你觉得这很慢?我认为您很难找到更快的模块。你需要对它进行基准测试,我严重怀疑你会从中获益多少。例如,您可以使用
List::MoreUtilsuniq,例如if (@a == uniq(@a))。但是那个子程序很简单,sub uniq { my %seen; grep { !$seen{$_}++ } @_; } -
它可能会尽可能快,但肯定比简单的赋值 %h = @a 慢。测试 @a == uniq(@a) 不能满足我的要求,因为只有键(偶数位置元素)需要是唯一的,而不是值。
-
好吧,那么你会知道
keys %h应该等于@a / 2,不是吗? -
是的,我同时也有同样的想法 ;-)
-
伟大的思想都一样。 ;)
标签: perl list hash duplicates checked