Perl: slicing an array of hashes

2019-02-28 15:31发布

问题:

The output of the code below is always empty. Not sure what I am doing wrong and would appreciate any help. How do I get to the values of a key in a specific hash in an array of hashes?

use strict;
use warnings;

my %dot1 = ('a'=>1,'b'=>2);
my %dot2 = ('a'=>3,'b'=>4);
my %dot3 = ('a'=>5,'b'=>6);
my %dot4 = ('a'=>7,'b'=>8);

my @array = (%dot1,%dot2,%dot3,%dot4);

my %x = $array[2];
my $y = $x->{'a'};

print "$y \n";

回答1:

If you want an array of hash references, you need to say so explicitly.

my @array = (\%dot1, \%dot2, \%dot3, \%dot4);
my %x = %{$array[2]};
my $y = $x{a};
print "$y\n";


回答2:

You don't have an array of hashes. You have an array that looks like a hash, where the keys a and b will be there four times each, in relatively random order.

print Dumper \@array;
$VAR1 = [
          'a',
          1,
          'b',
          2,
          'a',
          3,
          'b',
          4,
          'a',
          5,
          'b',
          6,
          'a',
          7,
          'b',
          8
        ];

Afterwards, you are using $x->{a}, which is the syntax to take the key a from the hashref $x, but you only ever declared a hash %a. That in turn breaks, because you give it an odd-sized list of one value.

Instead, add references to the hashes to your array. That way you will get a multi-level data structure instead of a flat list. Then make the x variable a scalar $x.

my %dot1 = ('a'=>1,'b'=>2);
my %dot2 = ('a'=>3,'b'=>4);
my %dot3 = ('a'=>5,'b'=>6);
my %dot4 = ('a'=>7,'b'=>8);

my @array = (\%dot1,\%dot2,\%dot3,\%dot4); # here


my $x = $array[2]; # here
my $y = $x->{'a'};

print "$y \n";

This will print 5.

You should read up on data structures in perlref and perlreftut.



回答3:

What you want to do is add references to your hashes to your @array, otherwise perl will evaluate the hashes in list context.

my @array = (\%dot1,\%dot2,\%dot3,\%dot4);
my $x = $array[2];
my $y = $x->{'a'};

print "$y \n";