3

我想比较两个数组散列,看看它们是否相等。也就是说,键值应该包含相同的元素。

my %h1 = (
    w1 => ['3','1','2'],
    e2 => ['6','2','4'],
    r1 => ['8', '1'],
);

my %h2 = (
    w1 => ['3','1','2'],
    e2 => ['6','2','4'],
    r1 => ['8','1'],
);

 my %h3 = (
    w1 => ['3','1','2'],
    e2 => ['6','2','4'],
    r1 => ['4','1'],
);

my $i = 0;

foreach ( keys %h2 ){
    my $conditional = scalar keys %h2;  # 3
    if ([sort @{$h1{$_}}] ~~ [sort @{$h2{$_}}]) {
        $i++;
    }
    if ($i eq $conditional){
        print "true\n";
    }
}

比较%h1并且%h2应该返回 true,因为它们是相等的。比较%h1%h3打印什么。1)有没有更好的方法来做到这一点?

编辑

我想在不使用模块中的函数的情况下做到这一点。

4

3 回答 3

4

试试Test::Deep::NoTest,它处理Test::Deep所做的一切,除了它只返回 true 或 false 而不输出 TAP 测试。

print "true" if eq_deeply(\%h1, \%h2)
于 2013-04-03T17:43:38.630 回答
3

Data::Dumper是序列化数据结构的核心模块。然后您可以测试序列化的字符串相等性。

use Data::Dumper;
$Data::Dumper::Sortkeys = 1;
if (Dumper(\%hash1) eq Dumper(\%hash2)) {
    print "hashes are equal\n";
}

如果 evenData::Dumper是禁止的,请编写您自己的将 HoA 转换为字符串的序列化例程,并比较字符串。只要确保您不会被返回哈希键的随机顺序绊倒(这就是$Data::Dumper::Sortkeys=1上面示例中的行)。

于 2013-04-03T17:54:24.427 回答
1

我会为每个操作创建单独的子程序:测试数组是否相等且哈希值相同:

sub is_arrays_equal($$) {
    my ($a, $b) = @_;
    if (scalar @$a != scalar @$b) {
        return 0;
    }
    for my $i (0 .. $#{$a}) {
        if ($a->[$i] ne $b->[$i]) {
            return 0;
        }
    }
    return 1;
}

sub is_hoa_equal($$) {
    my ($a, $b) = @_;
    if (scalar(keys %$a) != scalar(keys %$b)) {
        return 0;
    }
    for my $k (keys %$a) {
        if (exists $b->{$k}) {
            if (ref $a->{$k} ne 'ARRAY' || ref $b->{$k} ne 'ARRAY' || !is_arrays_equal($a->{$k}, $b->{$k})) {
                return 0;
            }
        }
        else {
            return 0;
        }
    }
    return 1;
}

注意:将 'ne' 更改为 '!=' 或添加逻辑来比较您的标量值。

由于对每个数组进行排序和其他繁重的数据处理,您的解决方案并不好。如果您需要对所有类型的哈希进行相等性测试(不仅仅是我的解决方案中的 HoA),只需添加标量测试和哈希测试,这将是主子的递归调用,如下所示:

sub arrays_equal {
    my ( $a, $b ) = @_;
    if ( scalar @$a != scalar @$b ) {
        return 0;
    }
    for my $i ( 0 .. $#{$a} ) {
        my $va = $a->[$i];
        my $vb = $b->[$i];
        if ( ref $va ne ref $vb ) {
            return 0;
        }
        elsif ( ref $va eq 'SCALAR' && $va ne $vb ) {
            return 0;
        }
        elsif ( ref $va eq 'ARRAY' && !arrays_equal( $va, $vb ) ) {
            return 0;
        }
        elsif ( ref $va eq 'HASH' && !hashes_equal( $va, $vb ) ) {
            return 0;
        }
    }
    return 1;
}

sub hashes_equal {
    my ( $a, $b ) = @_;
    if ( scalar( keys %$a ) != scalar( keys %$b ) ) {
        return 0;
    }
    for my $k ( keys %$a ) {
        if ( exists $b->{$k} ) {
            my $va = $a->{$k};
            my $vb = $b->{$k};
            if ( ref $va ne ref $vb ) {
                return 0;
            }
            elsif ( ref $va eq 'SCALAR' && $va ne $vb ) {
                return 0;
            }
            elsif ( ref $va eq 'ARRAY' && !arrays_equal( $va, $vb ) ) {
                return 0;
            }
            elsif ( ref $va eq 'HASH' && !hashes_equal( $va, $vb ) ) {
                return 0;
            }
        }
        else {
            return 0;
        }
    }
    return 1;
}

此代码将标量检查为字符串。您可以像这样添加 is_number 或 smth,或者只是将 'ne' 更改为 '!=' (但如果不仅有数字,请注意警告)。

于 2013-04-04T11:37:04.160 回答