user2013387
user2013387

Reputation: 203

Traversing Array of Hashes in perl

I have a structure as below:

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

Now I want to traverse the first hash and the elements in it.. How can I do it?

When I do a dumper of $var1 it gives me Array and when on @var1 it says a hash.

Upvotes: 4

Views: 3607

Answers (4)

smithfarm
smithfarm

Reputation: 333

With one peek at amon's up-voted comment above (thanks, amon!) I was able to write this little ditty:

#!/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"

Upvotes: 0

Paul Alan Taylor
Paul Alan Taylor

Reputation: 10680

First off, you're going to trip Perl's strict mode with your variable declaration that includes barewords.

With that in mind, complete annotated example given below.

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";
    }
}

Upvotes: 4

Patt Mehta
Patt Mehta

Reputation: 4204

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 = [] is a reference to an anonymous array

  2. using the @ sigil before it as in $var1 gives you the access to the array it is referencing. So analogous to foreach (@arr) {...} you would do foreach (@{$var1}) {...}.

  3. Now, the elements in the array that you have provided @{$var1} are anonymous (means not named) too, but they are anonymous hashes, so just like with the arrayref, here we do %{$hash_reference} to get access to the hash referenced by $hash_reference. Here, $hash_reference is $var.

  4. After accessing the hash using %{$var} it becomes easy to access the keys of the hash using keys(%$var) or keys(%{$var}). Since the result returned is an array of keys therefore we can use keys(%{$var}) inside foreach (keys(%{$var})) {...}.

  5. We access the scalar value inside an anonymous hash by using a key like $hash_reference->{$keyname}, that's all the code did.

  6. In case your array contained anonymous hashes of arrays like : $var1=[ { akey=>["b", "c"], mkey=>["n", "o"]} ]; then, this is how you will access the array values:

    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,
    ...
    

Practice it more and regularly, it will soon become easy for you to break complex structures into such combinations. This is how I created a large parser for another software, it is full of answers to your questions :)

Upvotes: 1

Mat
Mat

Reputation: 206737

You iterate over the array as you would with any other array, and you'll get hash references. Then iterate over the keys of each hash as you would with a plain hash reference.

Something like:

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

Upvotes: 4

Related Questions