Reputation: 19
I am a beginner with Perl, and am trying to write a script to compare the two hashes and print the values in the first hash that are not found in the second. Although I know the script should be very simple, I am not sure why mine is not working. Any help would be much appreciated.
My script so far:
#!/usr/bin/perl
use strict;
use warnings;
use vars qw($a $b $c $d $hash1 %hash1 $info1 $hash2 %hash2);
open (FILE1, "<file1.txt") || die "$!\n Couldn't open file1.txt\n";
while (<FILE1>){
chomp (my $line=$_);
my ($a, $b, $c, $d) = split (/\t/, $line);
if ($a){
$hash1 -> {$a} -> {info1} = "$b\t$c\t$d";
}
$info1=$hash1->{$a}->{info1};
}
open (FILE2, "<file2.txt") || die "$!\n Couldnt open file2.txt \n";
open (Output, ">Output.txt")||die "Can't Open Output file";
while (<FILE2>) {
chomp (my $line=$_);
my ($a, $b, $c, $d) = split (/\t/, $line);
if ($a){
$hash2 -> {$a} -> {info2} = "$b\t$c\t$d";
}
foreach (my $hash1->{$a}) {
if (!exists $hash2{$a}) {
print Output "$a\t$info1\n";
}
}
}
close FILE1;
close FILE2;
close Output;
print "Done!\n";
Upvotes: 0
Views: 286
Reputation: 50637
You can take all keys from %h1
and delete all keys from %h2
, which leaves only keys which are not in %h2
,
my %h1 = qw(k1 v1 k2 v2 k3 v3 k4 v4);
my %h2 = qw(k1 v1 k2 v2 k3 v3);
my %not_found_in_h2 = %h1;
delete @not_found_in_h2{keys %h2};
print "$_\n" for values %not_found_in_h2;
output
v4
Upvotes: 2
Reputation: 9770
I've found what appears to be multiple bugs in your program. I've reformatted your code and left comments to the precise locations of the bugs below:
#!/usr/bin/env perl
use strict;
use warnings;
use autodie;
# use 3-arg open
open my $file1, '<', 'file1.txt'; # no need to check errors with autodie
# declare your lexical variables in the proper scope
my $hash1 = {};
while (my $line = <$file1>) {
chomp $line;
my ($a, $b, $c, $d) = split /\t/, $line;
if ($a) {
$hash1->{$a}{info1} = "$b\t$c\t$d";
}
# It's unclear why you are assigning to this variable?
my $info1 = $hash1->{$a}{info1};
}
open my $file2, '<', 'file2.txt';
open my $output, '>', 'Output.txt';
# same thing here: declare your lexical variables
my $hash2 = {};
while (my $line = <$file2>) {
chomp $line;
my ($a, $b, $c, $d) = split (/\t/, $line);
if ($a) {
$hash2->{$a}{info2} = "$b\t$c\t$d";
}
# BUG: You can't iterate over a hash directly, but you
# can iterate over the keys of a hash.
foreach my $key (keys %$hash1) {
# BUG: You wrote `$hash2{$a}`, but probably meant `$hash2->{$a}`.
if (!exists $hash2->{$key}) {
# BUG: I think you probably meant for the following
# `$info1` reference to refer to the value inside
# `$hash1->{a}` and not the last line from the prior
# loop. Using lexical variables will detect these
# types of problems.
my $info1 = $hash1->{$key}{info1};
print {$output} "$key\t$info1\n";
}
}
}
# If you use lexical file handles, calling close is not required. They
# get closed at the end of the containing scope, which in this case is
# the end of the script.
print "Done!\n";
Upvotes: 1