【问题标题】:Perl comparing two hashesPerl 比较两个哈希
【发布时间】:2015-06-08 13:58:23
【问题描述】:

我是 Perl 的初学者,我正在尝试编写一个脚本来比较两个散列并打印第一个散列中没有在第二个散列中找到的值。尽管我知道脚本应该非常简单,但我不确定为什么我的脚本不起作用。任何帮助将非常感激。

到目前为止我的脚本:

#!/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";

【问题讨论】:

  • 拥有同名的不同变量(除了印记),如 %hash1$hash1 只会让你伤心。
  • 这个小脚本中有大量的不良做法。我强烈推荐阅读 Perl 最佳实践 以避免使用 Perl 的许多陷阱。在这个时候学习 Perl 没有必要养成坏习惯。
  • 特别是,强烈建议不要使用use vars pragma。此外,我们看不到您的输入文件是什么。因此,很难判断您的程序要做什么。

标签: perl hash compare


【解决方案1】:

您可以从%h1 中取出所有键,并从%h2 中删除所有键,只留下不在%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;

输出

v4

【讨论】:

    【解决方案2】:

    我发现您的程序中似乎存在多个错误。我已重新格式化您的代码并将 cmets 保留在以下错误的确切位置:

    #!/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";
    

    【讨论】:

      猜你喜欢
      • 2016-09-05
      • 2011-09-12
      • 1970-01-01
      • 1970-01-01
      • 2018-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多