如何在不使用子例程或模块的情况下比较perl中不同级别的两个哈希值?

时间:2018-06-06 17:59:07

标签: arrays perl hash

我的数组是

my @arr = ('mars','earth','jupiter');
my @arr1 = ('mercury','mars');
my @arr2 = ('planet','earth','star','sun','planet2','mars');
%space = ( 'earth'=>{
              'planet'=> {
                     '1' =>'US',
                     '2' =>'UK'
                    },
              'planet2'=>{
                      '1' =>'AFRICA',
                      '2' =>'AUS'
                   }
               },
        'sun'=>{
               'star' =>{
                       '1' =>'US',
                       '2' =>'UK'
                     }
             },
        'mars' =>{
                 'planet2' =>{
                               '1' =>'US',
                       '2' =>'UK'
                     }
             }

       );

现在我按以下方式比较前两个数组

foreach (@arr)
{
  $arr_hash{$_} =1;
}
foreach my $name (keys %space)
{
  foreach my $key (keys %{$space{$name}})
  if ($arr_hash{$name} !=1)
  {
    #do something
  }

现在我应该如何比较第三个阵列?我正在尝试这样的事情

  else
  {
     if($arr2_hash{$key}{$name} !=1)
     {
       #do something else
     }

我想检查行星+地球对(例如,key1和key2的组合应该与@ arr2中的第一个和第二个元素匹配)是否也存在于%space中? 有什么帮助吗?

1 个答案:

答案 0 :(得分:4)

我现在已经在Perl中完成了两次。一次为Test::More's is_deeply(),另一次为perl5i's are_equal()。做得对并不简单。没有子程序的做是很愚蠢的。如果您想了解如何完成此操作,请查看are_equal(),尽管可以做得更好。

但我认为你实际上并不需要比较两个哈希值。

我认为您需要检查%space中是否存在各种数组中的内容。例如......

my @arr = ('mars','earth','jupiter');

那将是真实,真实和虚假。

my @arr1 = ('mercury','mars');

错,是的。

my @arr2 = ('planet','earth','star','sun','planet2','mars');

假设这些是成对的,它们都是真的。

我将使用比描述内容的@arr更好的变量名,而不是结构的类型。我也会假设use strict; use warnings; use v5.10;存在。

前两个很简单,遍历数组并检查%space中是否有条目。我们可以在一个循环中完成两个数组。

for my $name in (@names1, @names2) {
    print "$name...";
    say $space{$name} ? "Yes" : "No";
}

第三组有点棘手,如何布置数据会让事情变得更难。将对放在列表中是很尴尬的,这就是哈希的用途。这会更有意义......

my %object_types = (
    earth => "planet", sun => "star", mars => "planet2"
);

然后很容易。检查$space{$name}{$type}是否为真。

for my $name (keys %object_types) {
    my $type = $object_types{$name};

    print "$name / $type...";
    say $space{$name}{$type} ? "Yes" : "No";
}

或者,如果您坚持使用数组,我们可以成对地遍历列表。

# $i will be 0, 2, 4, etc...
for( my $i = 0; $i < $#stellar_objects; $i+=2 ) {
    my($type, $name) = ($stellar_objects[$i], $stellar_objects[$i+1]);

    print "$name / $type...";
    say $space{$name}{$type} ? "Yes" : "No";
}

如果您要检查具有多个名称的类型的哈希,那该怎么办?

my %object_types = (
    planet =>['earth'],
    star =>['sun'],
    planet2 =>['earth','mars']
);

同样的想法,但我们需要在names数组上有一个内部循环。好好利用多个变量名有助于保持事物的正确性。

for my $type (keys %object_types) {
    my $names = $object_types{$type};

    for my $name (@$names) {
        print "$name / $type...";
        say $space{$name}{$type} ? "Yes" : "No";
    }
}

由于这些实际上是一组要搜索的对,因此将它们组合成一个大哈希是一种伤害。为此搜索提供更好的数据结构可能是成对列表。

my @searches = (
    [ planet => 'earth' ],
    [ star => 'sun' ],
    [ planet2 => 'earth' ],
    [ planet2 => 'mars' ],
);

for my $search (@searches) {
    my($type, $name) = @$search;
    print "$name / $type...";
    say $space{$name}{$type} ? "Yes" : "No";
}

为了记录,%space的设计很差。前两个级别很好,名称和类型,它是尴尬的国家哈希。

'sun'=>{
    'star' =>{
        # This part
        '1' =>'US',
        '2' =>'UK'
    }
},

这没有哈希的优点和所有缺点。哈希的优点是查找单个密钥非常快,但这使得将有趣的部分变为值时使其变得尴尬。如果密钥试图在哈希上强加订单,请使用数组。

sun => {
    star => [ 'US', 'UK' ]
},

然后,您可以获得国家/地区的列表:$countries = $space{$name}{$type}

如果您想要快速键查找并且顺序无关紧要,请使用哈希,其中键是存储的东西,值为1(只是&#34; true&#34;的占位符)。 / p>

sun => {
    star => { 'US' => 1, 'UK' => 1 }
},

这利用了散列键查找,并允许$space{$name}{$type}{$country}快速检查是否存在。 &#34;值&#34; (即使它们被存储为键)也保证是唯一的。这正式名称为set,是一组独特的价值观。

您可以在值中存储更多信息。