【问题标题】:Is there a simple way to validate a hash of hash element comparsion?有没有一种简单的方法来验证散列元素比较的散列?
【发布时间】:2011-11-22 09:41:43
【问题描述】:

有没有简单的方法来验证散列元素比较的散列?

我需要将哈希元素 $Table{$key1}{$key2}{K1}{Value} 的 Perl 哈希值与哈希中的所有其他元素进行比较

第三个键是 k1 到 kn,我想比较这些元素和其他键是否相同

if ($Table{$key1}{$key2}{K1}{Value} eq $Table{$key1}{$key2}{K2}{Value}
    eq  $Table{$key1}{$key2}{K3}{Value} ) 
{
   #do whatever
}

【问题讨论】:

  • “Kn key wille k1 to kn”是什么意思?
  • 第三个键不同,其他相同,第三个元素可能是 1 到 n...
  • 编辑您的问题,使其更清晰。

标签: perl hash


【解决方案1】:

这样的事情可能会奏效:

use List::MoreUtils 'all';

my @keys = map "K$_", 1..10;

print "All keys equal"
    if all { $Table{$key1}{$key2}{$keys[1]}{Value} eq $Table{$key1}{$key2}{$_}{Value} } @keys;

【讨论】:

    【解决方案2】:

    我会使用Data::Dumper 来帮助完成这样的任务,尤其是对于更普遍的问题(第三个键比'K1'...'Kn' 更随意)。使用Data::Dumper对数据结构进行字符串化,然后比较字符串。

    use Data::Dumper;
    
    # this line is needed to assure that hashes with the same keys output
    # those keys in the same order.
    $Data::Dumper::Sortkeys = 1;
    
    my $string1= Data::Dumper->Dump($Table{$key1}{$key2}{k1});
    
    for ($n=2; exists($Table{$key1}{$key2}{"k$n"}; $n++) {
    
        my $string_n = Data::Dumper->Dump($Table{$key1}{$key2}{"k$n"});
    
        if ($string1 ne $string_n) {
            warn "key 'k$n' is different from 'k1'";
        }
    
    }
    

    这可用于$Table{$key1}{$key2}{k7}{value} 本身包含复杂数据结构的更一般的情况。但是,当检测到差异时,它并不能帮助您找出差异在哪里。

    【讨论】:

      【解决方案3】:

      相当复杂的结构。您应该考虑使用object oriented programming techniques。这将大大简化您的编程和这些复杂结构的处理。

      首先,让我们稍微简化一下。当你说:

      $Table{$key1}{$key2}{k1}{value}
      

      你的意思是:

      my $value = $Table{$key1}->{$key2}->{k1};
      

      my $actual_value = $Table{$key1}->{$key2}->{k1}->{Value};
      

      我将假设第一个。如果我错了,请告诉我,我会更新我的答案。

      让我们简化一下:

      my %hash = %{$Table{$key1}->{$key2}};
      

      现在,我们只是在处理一个哈希。您可以使用两种技术:

      1. 将此哈希的键按值排序,如果两个键具有相同的值,则它们将在排序列表中彼此相邻,便于检测重复。优点是所有重复的键都将打印在一起。缺点是这是一种需要时间和资源的排序。
      2. 反转散列,因此它是按值作为键的,该键的值就是键。如果一个 key 已经存在,我们就知道另一个 key 有一个重复值。这比第一种技术更快,因为不涉及排序。但是,会检测到重复项,但不会一起打印。

      这是第一种技术:

      my %hash = %{$Table{$key1}->{$key2}};
      my $previous_value;
      my $previous_key;
      foreach my $key (sort {$hash{$a} cmp $hash{$b}} keys %hash) {
          if (defined $previous_key and $previous_value eq $hash{$key}) {
              print "\$hash{$key} is a duplicate of \$hash{$previous_key}\n";
          }
          $previous_value = $hash{$key};
          $previous_key = $key;   
      }
      

      第二个:

      my %hash = %{$Table{$key1}->{$key2}};
      my %reverse_hash;
      foreach $key (keys %hash) {
         my $value = $hash{$key};
         if (exists $reverse_hash{$value}) {
             print "\$hash{$reverse_hash{$value}} has the same value as \$hash{$key}\n";
         }
         else {
             $reverse_hash{$value} = $key;
         }
      }
      

      【讨论】:

      • 您需要取消引用$Table{$key1}->{$key2} 才能获得真正的哈希值,即my %hash = %{ $Table{$key1}->{$key2} };。否则,您将引用用作哈希键(尝试启用 warnings
      • OOP 方法:不,它不会简化事情。这将涉及更多代码和更多错误。查看我的功能方法以及它带来的简单和简洁的解决方案。 my %hash = $Table{$key1}->{$key2}; 不起作用应该是my %hash = %{$Table{$key1}->{$key2}}; 或更高效的my $hashref = $Table{$key1}->{$key2};
      【解决方案4】:

      解决问题的另一种方法是制作实用函数,如果所有键的某个函数返回相同的值,它将比较所有键:

      sub AllSame (&\%) {
        my ($c, $h) = @_;
        my @k = keys %$h;
        my $ref;
        $ref = $c->() for $h->{shift @k};
        $ref ne $c->() and return for @$h{@k};
        return 1
      }
      
      print "OK\n" if AllSame {$_->{Value}} %{$Table{$key1}{$key2}};
      

      但如果您开始以这种方式思考,您会发现这种方法更加通用(推荐方式):

      sub AllSame (@) {
        my $ref = shift;
        $ref ne $_ and return for @_;
        return 1
      }
      
      print "OK\n" if AllSame map {$_->{Value}} values %{$Table{$key1}{$key2}};
      

      如果映射操作很昂贵,您可以制作相同的惰性对应物:

      sub AllSameMap (&@) {
        my $c = shift;
        my $ref;
        $ref = $c->() for shift;
        $ref ne $c->() and return for @_;
        return 1
      }
      
      print "OK\n" if AllSameMap {$_->{Value}} values %{$Table{$key1}{$key2}};
      

      如果您只想要一些键子集,您可以使用哈希切片语法,例如:

      print "OK\n" if AllSame map {$_->{Value}} @{$Table{$key1}{$key2}}{map "K$_", 1..10};
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-06-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-25
        • 1970-01-01
        相关资源
        最近更新 更多