Reputation: 55
I want to search %instancesCD
for the contents of %instancesTH
; specifically, a match between the $file
and $position
keys and the associated value. If %instancesCD
contains a key/value from %instancesTH
, then $fp
is incremented. If %instancesCD
does not contain a key/value from %instancesTH
, then $fn
is incremented. Also, I apologize if the way I am referring to the hashes is incorrect; this is my first time using hashes.
This is what I have so far:
#!/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;
}
Thank you.
Upvotes: 2
Views: 88
Reputation: 54323
You need to iterate one of them and check for the existence of each key. Here is a verbose implementation.
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};
}
This will print x
. If you remove the x => 7
from %foo
, it will print nothing.
Here is there result of the extended chat session we had. A full program that compares the keys and values, with unit tests.
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;
}
Upvotes: 2