tvStatic
tvStatic

Reputation: 966

Populating and accessing array of hashes

I have the following perl code:

@searchInfo = ();

sub main()
{
    processCmdLine();

    foreach my $info ( @searchInfo )
    {
        print "Search field: " . $info{field} . "\n";
        print "Search value: " . $info{value} . "\n";
    }
}

sub processCmdLine()
{
    while(@ARGV > 1)
    {
        $rec = {};
        $rec{field} = shift(@ARGV);
        $rec{value} = shift(@ARGV);
        print "$info{field} = $info{value}\n";
        push @searchInfo, $rec;
    }
}

When I run this, with a command like: script.pl f1 v1 f2 v2, I get the following output

f1 = v1
f2 = v2
Search field:
Search value:
Search field:
Search value:

I'm basing the code on this tutorial.

What is the reason why the hashes inside the array have empty values?

Upvotes: 0

Views: 88

Answers (2)

marquezc329
marquezc329

Reputation: 71

You shouldn't use @ARGV inside your subroutine. Use @_ instead and call the subroutine with @ARGV as a parameter. This way if you later want to pass a different array to the subroutine then you need only change the original call instead of hunting down all the places that you hardcoded the definitions. This will save time debugging for you and others coming in contact with your code. This will also let you toss an array with a slew of different values at the subroutine for testing, rather than having to test by typing args at the command line.

    sub processCmdLine() {
        while(@ARGV > 1) {    
            $rec = {};
            $rec{field} = shift(@ARGV);
            $rec{value} = shift(@ARGV);j
            print "$info{field} = $info{value}\n";
            push @searchInfo, $rec;
        }
    }

becomes:

    sub processCmdLine() {
        while(@_ > 1) {
            my %rec;
            ($rec{field}, $rec{value}) = @_;
            print "$info{field} = $info{value}\n";
            push @searchInfo, $rec;
        }
    }
    processCmdLine(@ARGV);

note: This examply only portrays my recommended change of @ARGV, and fixes the useless reference by creating a hash instead of a reference. It doesn't fix the design issues ikegami mentions in regards the creating of multiple single key hashes.

Upvotes: 0

ikegami
ikegami

Reputation: 386696

Always use use strict; use warnings;!!! It would tell you you're accessing a hashes named %info and %rec, but you don't have such variables.

Hash values are scalars. As such, they cannot contain hashes. This can be approximated by using references to hashes. You seem to realise this by using $rec = {};, but then you never use that variable again.

Fix:

my $rec = {};
$rec->{field} = shift(@ARGV);
$rec->{value} = shift(@ARGV);
push @searchInfo, $rec;

Cleaner fix:

my %rec;
$rec{field} = shift(@ARGV);
$rec{value} = shift(@ARGV);
push @searchInfo, \%rec;

Don't forget to fix the fetcher too:

print "Search field: $info->{field}\n";
print "Search value: $info->{value}\n";

But why are you creating whole bunch of hashes with one key?! Did you perhaps mean to do:

%search_info = @ARGV;

Then the fetcher would be

for my $key (keys(%search_info)) {
    my $val = $search_info{$key};
    print "Search field: $key\n";
    print "Search value: $val\n";
}

Upvotes: 1

Related Questions