【问题标题】:Compare values of keys across multiple hashes in Perl在 Perl 中比较多个哈希中的键值
【发布时间】:2014-02-05 16:07:40
【问题描述】:

我有一组哈希(使用 Tie::IxHash 保留键序列),我想比较每个键的值。哈希的数量可以变化。例如,我想计算键“1”被分配值“1”和“0”的次数。我知道如果我将散列放入一个散列数组中然后循环遍历它们,应该有一种很好的快速方法来计算值匹配,但是我被卡住了,无法自己弄清楚。

%hash1 = ( 1 => '1',
           2 => '1',
           3 => '0',
           4 => '0',
         );

%hash2 = ( 1 => '1',
           2 => '1',
           3 => '1',
           4 => '0',
         );

%hash3 = ( 1 => '1',
           2 => '1',
           3 => '0',
           4 => '1',
         );

%hash4 = ( 1 => '1',
           2 => '0',
           3 => '0',
           4 => '1',
         );

上述的预期结果是:

$key1: $agr1 = 4; $agr0 = 0;
$key2: $agr1 = 3; $agr0 = 1;
$key3: $agr1 = 1; $agr0 = 3;
$key4: $agr1 = 2; $agr0 = 2;

现在我最终做的是遍历第一个哈希的键,然后将它们与其他每个哈希进行比较,这显然是乏味和愚蠢的。

感谢您的帮助!

更正:我使用的是哈希,而不是哈希引用。相应地编辑了上面的代码。

【问题讨论】:

    标签: perl hash comparison


    【解决方案1】:

    伪类:

    # Build a list of refs to your hashes
    @a = { \%hash1, \%hash2, ... }
    
    # A container to hold the keys and counts
    $keys = {} 
    
    # Initialize the key container
    for my $h in @a
        for my $k in %$h
            $keys->{$k} = {0 => 0, 1 => 0} unless exists $keys->{$k}
    
    # Iterate once over all the keys and count occurrences
    # assumes input hash values can be only 0 or 1
    for my $k in %$keys
        for my $h in @a
            $keys->{$k}->{$h->{$k}}++ if exists $h->{$k};
    

    【讨论】:

      【解决方案2】:

      首先,您的哈希示例是错误的。 %hash = {}.

      如果你使用% 印记,你想要()。如果你想要一个哈希引用,它会是$hash = {}

      回到你的问题。你可以做这样的事情。

      这通常被称为“可见”哈希。

      # appending your example above....
      my @arr = (\%hash1, \%hash2, \%hash3, \%hash4);
      my $seen = {}; 
      
      # iterate over each hash
      for my $hash (@arr) {
          # iterate over each key in hash
          for my $k (keys %$hash) {
              my $val = $hash->{$k};
      
              # check $val and increment 
              if ($val) {
                  $seen->{$k}{1}++;
              } else {
                  $seen->{$k}{0}++;
              }   
          }   
      }
      
      for my $k ( sort keys %$seen ) { 
          # in case any value is 0/undef
          print "$k:  1 = "
            . ( $seen->{$k}->{0} ? $seen->{$k}->{0} : 0 ) . " 0 = "
            . ( $seen->{$k}->{0} ? $seen->{$k}->{0} : 0 ) . "\n";
      }
      

      哪些输出:

      $ perl test.pl
      1:  1 = 0 0 = 0
      2:  1 = 1 0 = 1
      3:  1 = 3 0 = 3
      4:  1 = 2 0 = 2
      

      【讨论】:

        【解决方案3】:

        这为您的结果提供了一些灵活性,因为您可以在@wanted 中输入任何所需的值。假设您的哈希实际上是哈希引用(在您的示例中不明确):

        my @hashes = ($hash1,$hash2,$hash3,$hash4);
        my %count;
        for my $hash (@hashes) {
            $count{ $_ }{ $hash->{$_} }++ for keys %$hash;
        }
        my @wanted = (1,0);
        for my $key (sort { $a <=> $b } keys %count) {
            my @result = map { "agr$_ = " . ($count{$key}{$_} || 0) . ';' } @wanted;
            print "key $key: @result\n";
        }
        

        输出:

        key 1: agr1 = 4; agr0 = 0;
        key 2: agr1 = 3; agr0 = 1;
        key 3: agr1 = 1; agr0 = 3;
        key 4: agr1 = 2; agr0 = 2;
        

        【讨论】:

        • 谢谢,循环工作正常。我还需要将协议值放入变量中,如我的问题所示,并在键之间进行汇总。您能否指出如何在您的代码中完成此操作?
        • 您问题中的变量都具有相同的名称 $agr0 或 $agr1。你需要为你想要的每个键和值说$agr_1_k1_v0 = $count{1}{0} || 0; $agr_1_k1_v1 ...。您需要的所有信息都在 %count 哈希中,使用 Data::Dumper 打印它,您会看到。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-09-12
        • 2018-06-28
        • 1970-01-01
        • 2019-01-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多