如何比较哈希perl的哈希值

时间:2017-03-23 08:32:43

标签: perl

我想在%instancesCD中搜索%instancesTH的内容;具体而言,$file$position键之间的匹配以及相关值。如果%instancesCD包含来自%instancesTH的键/值,则$fp会递增。如果%instancesCD不包含%instancesTH的键/值,则$fn会递增。另外,如果我指的是哈希的方式不正确,我道歉;这是我第一次使用哈希。

这是我到目前为止所做的:

#!/usr/bin/perl
use warnings;
use strict;

print_accuracy(determine_accuracy(determine_instancesTH(), determine_instancesCD()));

sub determine_accuracy {
my (%instancesTH, %instancesCD) = (@_);
    foreach my $file (keys %instancesTH) {
        foreach my $pos (keys %{$instancesTH{$file} } ) {
                if {
                # ... 
                    my $fp++;
                }
                else {
                    my $fn++;
                }
         }
     }
    return $tp, $fn;
}

sub print_accuracy {
    my ($tp, $fn) = (@_);
    print "True Positives: $tp\n";
    print "False Negatives: $fn\n\n";
}

sub determine_instancesA {
    # ... 
    return %instancesA;
}

sub determine_instancesB {
    # ... 
    return %instancesB;
}

谢谢。

1 个答案:

答案 0 :(得分:2)

您需要迭代其中一个并检查每个密钥的存在。这是一个冗长的实现。

use strict;
use warnings;

my %foo = ( a => 1, b => 2, c => 3, x => 7 );
my %bar = ( x => 7, y => 8, z => 9 );

foreach my $key ( keys %bar ) {
    CORE::say $key if exists $foo{$key} && $bar{$key} eq $foo{$key};
}

这将打印x。如果您从x => 7中删除%foo,则不会打印任何内容。

这是我们进行的扩展聊天会话的结果。一个完整的程序,用于比较键和值,以及单元测试。

use strict;
use warnings;
use Test::More;

my @test_cases = (
    {
        'name' => 'all keys match',
        'th'   => {
            surfacecharge => {
                87 => 'negatively charged',
            },
        },
        'cd' => {
            surfacecharge => {
                87 => 'negatively charged',
            },
        },
        'true positives'  => { surfacecharge => 1, }, # here 
        'false negatives' => { surfacecharge => 0, }, # but this one comes out undef
    },
    {
        'name' => 'key matches, value does not',
        'th'   => {
            surfacecharge => {
                87 => 'negatively charged',
            },
        },
        'cd' => {
            surfacecharge => {
                87 => 'positively charged',
            },
        },
        'true positives'  => { surfacecharge => 0, },
        'false negatives' => { surfacecharge => 1, },
    },
    {
        'name' => 'two matching keys',
        'th'   => {
            surfacecharge => {
                87 => 'negatively charged',
                88 => 'chronically tired',
            },
        },
        'cd' => {
            surfacecharge => {
                87 => 'negatively charged',
                88 => 'chronically tired',
            },
        },
        'true positives'  => { surfacecharge => 2, },
        'false negatives' => { surfacecharge => 0, },
    },
    {
        'name' => 'two/zero, one/one',
        'th'   => {
            surfacecharge => {
                87 => 'negatively charged',
                88 => 'chronically tired',
            },
            areasurcharge => {
                1 => 'stuff',
                2 => 'goo',
            },
        },
        'cd' => {
            surfacecharge => {
                87 => 'negatively charged',
                88 => 'chronically tired',
            },
            areasurcharge => {
                1 => 'stuff',
                0 => 'do not want',
            },
        },
        'true positives'  => { surfacecharge => 2, areasurcharge => 1, },
        'false negatives' => { surfacecharge => 0, areasurcharge => 1, },
    },
);

foreach my $test (@test_cases) {
    my ( $true_positives, $false_negatives ) = determine_accuracy( $test->{th}, $test->{cd} );
    is_deeply $true_positives,  $test->{'true positives'},  "$test->{name}: true positives";
    is_deeply $false_negatives, $test->{'false negatives'}, "$test->{name}: false negatives";
}
done_testing;

sub determine_accuracy {
    my ( $instancesTH, $instancesCD ) = @_;

    my $tp;
    my $fn;

    foreach my $file ( keys %{$instancesTH} ) {
        $tp->{$file} = 0;
        $fn->{$file} = 0;
        foreach my $pos ( keys %{ $instancesTH->{$file} } ) {
            if ( exists $instancesCD->{$file}->{$pos}
                && $instancesCD->{$file}->{$pos} eq $instancesTH->{$file}->{$pos} )
            {
                $tp->{$file}++;
            }
            else {
                $fn->{$file}++;
            }
        }
    }
    return $tp, $fn;
}