Perl:使重复哈希键的声明成为致命错误?

Perl 中有没有办法在声明时使重复哈希键的存在成为错误?

例如,对于这样的脚本:

测试文件

#!/usr/bin/perl

my %hash = (
             'a' => 'valid',
             'b' => 'valid',
             'c' => 'valid',
             'a' => 'duplicate'
           );

我想在运行时看到这样的东西:

$ perl ./test.pl
duplicate hash key at ./test.pl line 7, near 'a' => 'duplicate'
Execution of ./test.pl aborted due to compilation errors.

理想情况下,我希望保持哈希声明语法相同。有什么办法可以做到这一点吗?

回答

使用绑定的 hash,您可以覆盖存储散列值的机制。

package Hash::DupesNotAllowed;
use Carp;
sub TIEHASH  { bless {}, $_[0] }  # borrowed from  Tie::StdHash
sub FETCH    { $_[0]->{$_[1]} }
sub FIRSTKEY { my $a = scalar keys %{$_[0]}; each %{$_[0]} }
sub NEXTKEY  { each %{$_[0]} }
sub EXISTS   { exists $_[0]->{$_[1]} }
sub DELETE   { delete $_[0]->{$_[1]} }
sub CLEAR    { %{$_[0]} = () }
sub SCALAR   { scalar %{$_[0]} }

sub STORE {
    my ($self,$key,$value) = @_;
    if (exists($self->{$key})) {
        croak "Duplicate key '$key'";
    }
    $self->{$key} = $value;
    return;
}
1;


package main;
use Hash::DupesNotAllowed;
my (%h1, %h2, %h3);
tie %h2, 'Hash::DupesNotAllowed';
tie %h3, 'Hash::DupesNotAllowed';

%h1 = (a => 'one', b => 'two', a => 'three');    # ok
%h2 = (a => 'one', b => 'two', c => 'three');    # ok
%h3 = (a => 'one', b => 'two', a => 'three');    # "Duplicate key"


回答

要检查重复项,可以使用

grep !$seen{$_}++, LIST

要获取每个重复项中的第一个,我们可以修改如下:

grep ++$seen{$_} == 2, LIST

但是假设我们只想检查@_. 我们可以使用以下任何一种:

grep ++$seen{$_} == 2, @_[ map $_*2,  0 .. $#_/2 ]

grep ++$seen{$_} == 2, map $_[$_*2],  0 .. $#_/2

grep ++$seen{ $_[$_*2] } == 2, 0 .. $#_/2

所以我们可以使用这个:

sub check_for_dup_keys {
   my %seen;
   my @dups =
      grep ++$seen{ $_[$_*2] } == 2,
         0 .. $#_/2;
   die("Duplicate keys: @dupsn") if @dups;
   return @_;
}

my %hash = check_for_dup_keys(
   'a' => 'valid',
   'b' => 'valid',
   'c' => 'valid',
   'a' => 'duplicate',
);


以上是Perl:使重复哈希键的声明成为致命错误?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>