在Perl中遍历哈希数组

4
我有以下这样的一个结构:
my $var1 = [{a=>"B", c=>"D"}, {E=>"F", G=>"H"}];

现在我想遍历第一个哈希表以及其中的元素。我该怎么做?
当我对$var1进行转储时,它给出Array,而对于@var1则表示一个哈希表。

我喜欢这个问题,这也是我开始的方式 :D - Patt Mehta
4个回答

4

首先,你的变量声明包含裸字会触发Perl的严格模式。

基于此,请参考以下完整的注释示例。

use strict;

my $test = [{'a'=>'B','c'=>'D'},{'E'=>'F','G'=>'H'}];

# Note the @{ $test }
# This says "treat this scalar reference as a list".
foreach my $elem ( @{ $test } ){
    # At this point $elem is a scalar reference to one of the anonymous
    # hashes
    #
    # Same trick, except this time, we're asking Perl
    # to treat the $elem reference as a reference to hash
    #
    # Hence, we can just call keys on it and iterate
    foreach my $key ( keys %{ $elem } ){
        # Finally, another bit of useful syntax for scalar references
        # The "point to" syntax automatically does the %{ } around $elem
        print "Key -> $key = Value " . $elem->{$key} . "\n";
    }
}

4

您可以像处理其他数组一样迭代该数组,并获得哈希引用。然后,像处理普通哈希引用一样迭代每个哈希键。

示例代码如下:

foreach my $hash (@{$var1}) {
  foreach my $key (keys %{$hash}) {
    print $key, " -> ", $hash->{$key}, "\n";
  }
}

所以,如果我需要访问这个结构的第一个元素……应该是:@$var1[0]->{'a'}。我说得对吗? - user2013387
是的,它运行了。谢谢大家。现在我明白了这个概念... :) - user2013387
3
$arrayref 是一个数组的引用时,要访问其中一个元素可以使用 $arrayref->[0](注意保持原有符号 $ 和箭头 ->)。另一种写法是 $$arrayref[0]。同样地,我们可以通过哈希表的引用访问其中的元素,例如 $hashref->{a}(或者 $$hashref{a})。如果数组的第一个元素是一个哈希表的引用,我们可以像这样访问其中的一个成员:$var->[0]->{a}。在下标之间省略箭头也是可以的,例如 $var->[0]{a}(或者 $$var[0]{a})。但是不要在下标中使用 @% 符号,因为这会告诉 Perl 你想要的是多个值或者一个切片。 - amon
谢谢,amon。我已经收藏了这个链接:D 当有人能够对你已经知道的东西进行更正时,真的会增加知识:D - Patt Mehta
我在想当数据被定义为 my @var1 = ({a=>"B", c=> "D"}, {E=>"F", G=>"H"}); 时会变成什么样子。 - pevik

1
C:\wamp\bin\perl\bin\PERL_2~1\BASIC_~1\REVISION>type traverse.pl
my $var1=[{a=>"B", c=>"D"},{E=>"F", G=>"H"}];
foreach my $var (@{$var1}) {
  foreach my $key (keys(%$var)) {
    print $key, "=>", $var->{$key}, "\n";
  }
  print "\n";
}


C:\wamp\bin\perl\bin\PERL_2~1\BASIC_~1\REVISION>traverse.pl
c=>D
a=>B

G=>H
E=>F

  1. $var1 = []是一个匿名数组的引用。

  2. 在它前面使用@符号,如$var1,可以让您访问它所引用的数组。因此,类似于foreach (@arr) {...},您将执行foreach (@{$var1}) {...}

  3. 现在,您提供给@{$var1}的数组元素也是匿名的(即没有名称),但它们是匿名哈希,因此就像使用数组引用一样,在这里我们使用%{$hash_reference}来访问由$hash_reference引用的哈希表。在这里,$hash_reference$var

  4. 在使用%{$var}访问哈希表后,通过keys(%$var)keys(%{$var})轻松访问哈希表的键。由于返回的结果是键的数组,因此我们可以在foreach (keys(%{$var})) {...}中使用keys(%{$var})

  5. 我们使用类似$hash_reference->{$keyname}这样的键来访问匿名哈希中的标量值,这就是代码所做的全部。

  6. 如果您的数组包含匿名哈希的数组,例如: $var1=[ { akey=>["b", "c"], mkey=>["n", "o"]} ]; 那么,这就是您将如何访问数组值:

    C:\wamp\bin\perl\bin\PERL_2012\BASIC_PERL\REVISION>type traverse.pl
    my $var1=[ {akey=>["b", "c"], mkey=>["n", "o"]} ];
    
    foreach my $var (@{$var1}) {
      foreach my $key (keys(%$var)) {
        foreach my $elem (@{ $var->{$key} }) {
          print "$key=>$elem,";
        }
        print "\n...\n";
      }
      print "\n";
    }
    C:\wamp\bin\perl\bin\PERL_2012\BASIC_PERL\REVISION>traverse.pl
    mkey=>n,mkey=>o,
    ...
    akey=>b,akey=>c,
    ...
    
多加练习并且定期进行,你很快就能够将复杂的结构分解成这样的组合。这就是我为另一个软件创建了一个 大型解析器 的方法,它充满了你的问题的答案 :)

0

通过浏览amon上面受欢迎的评论(谢谢,amon!),我能够写出这个小曲调:

#!/usr/bin/perl
# Given an array of hashes, print out the keys and values of each hash.

use strict; use warnings;
use Data::Dump qw(dump);

my $var1=[{A=>"B",C=>"D"},{E=>"F",G=>"H"}];
my $count = 0;

# @{$var1} is the array of hash references pointed to by $var1
foreach my $href (@{$var1})
{
    print "\nArray index ", $count++, "\n";
    print "=============\n";

    # %{$href} is the hash pointed to by $href
    foreach my $key (keys %{$href})
    {
            # $href->{$key} ( ALT: $$href{$key} ) is the value
            # corresponding to $key in the hash pointed to by
            # $href
            # print $key, " => ", $href->{$key}, "\n";
            print $key, " => ", $$href{$key}, "\n";
    }

print "\nCompare with dump():\n";
dump ($var1);

print "\nJust the first hash (index 0):\n";
# $var1->[0] ( ALT: $$var1[0] ) is the first hash reference (index 0)
# in @{$var1}
# dump ($var1->[0]);
dump ($$var1[0]);

#print "\nJust the value of key A: \"", $var1->[0]->{A}, "\"\n";
#print "\nJust the value of key A: \"", $var1->[0]{A}, "\"\n";
print "\nJust the value of key A: \"", $$var1[0]{A}, "\"\n"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接