【问题标题】:How to compare two hashes of different levels in perl without using sub routines or modules?如何在不使用子例程或模块的情况下比较 perl 中不同级别的两个哈希?
【发布时间】:2018-06-06 17:59:07
【问题描述】:

我的数组是

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 中? 有什么帮助吗?

【问题讨论】:

  • 这就像一个家庭作业。昨天或前一天有人问过类似的问题。
  • @Andrey 你能指出我正确的方向吗?我真的很难让这件事继续下去。昨天问的那个问题是否有我当前查询的答案?
  • 昨天问的答案有类似的哈希值。但任务不同:stackoverflow.com/questions/50701681/…
  • 如果要比较 arr2 和 %space ,为什么需要 arr 和 arr1 ?
  • 如果这是家庭作业,我可以理解为什么没有模块。但是没有子程序?这只是糟糕的软件工程。

标签: arrays perl hash


【解决方案1】:

我已经在 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']
);

同样的想法,但我们需要对名称数组进行内部循环。善用复数变量名有助于保持直截了当。

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(只是“true”的占位符)。

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

这利用了哈希键查找并允许$space{$name}{$type}{$country} 快速检查是否存在。 “值”(即使它们存储为键)也保证是唯一的。这正式称为set,一个唯一值的集合。

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

【讨论】:

  • 并且您的 %object_types {earth}{planet2} 缺少匹配项。假设您的 %object_types = (planet =>{'earth'},star =>{'sun'},planet2 =>{'地球','火星'});你现在怎么查?
  • @AnaPliskova 你的意思是每种类型都有一个名称列表吗? %object_types = (planet =&gt;['earth'],star =&gt;['sun'],planet2 =&gt;['earth','mars']); 您需要对名称进行内部循环。我将在其中进行编辑。
  • 是的,解释得很清楚。你应该申请我的学校,我希望能学到更多
  • @AnaPliskova 我受宠若惊,谢谢。 :) 编辑已启动。
  • @AnaPliskova 如果他们解决了您的问题,您真的应该接受答案。 :-)
猜你喜欢
  • 2010-11-19
  • 1970-01-01
  • 2010-11-17
  • 1970-01-01
  • 2011-09-12
  • 1970-01-01
  • 2016-09-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多