buchi2 has asked for the wisdom of the Perl Monks concerning the following question:

Hello!

In a hash I have some arrays. This I get work. But now I want to build several of this hashes an array. I did it with push. But how I can get out now a value?

#!/usr/bin/perl -w my %hierhash; my @feld; my @hashfeld; my $wert; @hashfeld = (); %hierhash = &dofn(0,5,1); print "1 $hierhash{'var2'}[3] \n"; push(@hashfeld,%hierhash); %hierhash = &dofn(0,5,2); print "2 $hierhash{'var2'}[3] \n"; push(@hashfeld,%hierhash); $wert = $hashfeld[0]->{'var2'}[3]; print "$wert \n"; sub dofn () { my ($i, $ivon, $ibis, $imal); my %hashfn; $ivon = $_[0]; $ibis = $_[1]; $imal = $_[2]; for ($i = $ivon; $i < $ibis; $i++) { push(@{$hashfn{'var1'}}, $i*$imal); push(@{$hashfn{'var2'}}, $i*$imal*10.); push(@{$hashfn{'var3'}}, $i*$imal*20.); } return %hashfn; }
Regards, buchi

Replies are listed 'Best First'.
Re: how to access array of hash with arrays?
by roboticus (Chancellor) on Jul 25, 2017 at 14:32 UTC

    buchi2

    You were close: Your problem is the push(@hashfeld,%hierhash) statement. It's turning your hash into a list and pushing the entire list onto your array. You want to push a hash *reference*, like push(@hashfeld, {%hierhash}). This creates a new hash reference (the curly braces) and copies the hash into the reference. Then it pushes the *reference* onto your @hashfeld array.

    Here's your program with just a couple tweaks:

    $ perl pm_1195995.pl #!/usr/bin/perl use strict; use warnings; use Data::Dump 'pp'; my %hierhash; my @feld; my @hashfeld; my $wert; @hashfeld = (); %hierhash = &dofn(0,5,1); print "1 $hierhash{'var2'}[3] \n"; push(@hashfeld, { %hierhash }); %hierhash = &dofn(0,5,2); print "2 $hierhash{'var2'}[3] \n"; push(@hashfeld, { %hierhash }); $wert = $hashfeld[0]->{'var2'}[3]; print "$wert \n"; print pp(\@hashfeld), "\n\n"; sub dofn () { my ($i, $ivon, $ibis, $imal); my %hashfn; $ivon = $_[0]; $ibis = $_[1]; $imal = $_[2]; for ($i = $ivon; $i < $ibis; $i++) { push(@{$hashfn{'var1'}}, $i*$imal); push(@{$hashfn{'var2'}}, $i*$imal*10.); push(@{$hashfn{'var3'}}, $i*$imal*20.); } return %hashfn; } $ perl pm_1195995.pl 1 30 2 60 30 [ { var1 => [0 .. 4], var2 => [0, 10, 20, 30, 40], var3 => [0, 20, 40, 60, 80], }, { var1 => [0, 2, 4, 6, 8], var2 => [0, 20, 40, 60, 80], var3 => [0, 40, 80, 120, 160], }, ]

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

      OK, I got a bit bored, so I tweaked up your program a little.

      First, I'd suggest always putting use strict; and use warnings; at the start of your programs to pick up some free error-checking.

      Next, you're using function prototypes by putting parenthesis on the sub dofn () { line--Don't do that until you learn how prototypes work in perl. (Once you *do* learn that, you'll find that prototypes are only rarely desireable.).

      Third: many people find it cleaner to declare the variable when it's needed, rather than at the top of the block. Declaring the variables later limits their scope and makes it simpler to reason about your code.

      Fourth, you can declare your function arguments *and* load them at the same time using an array assignment.

      Fifth: you don't always need to use parenthesis on function calls, such as push.

      Finally, rather than returning a hash, you could return a hash reference from your function, so you don't need to create a hash reference when putting the data in the array each time.

      Making these few changes gives you:

      $ cat pm_1195995.pl #!/usr/bin/perl use strict; use warnings; use Data::Dump 'pp'; my @hashfeld = (); push @hashfeld, dofn(0,5,1); print "1 $hashfeld[0]{var2}[3]\n"; push @hashfeld, dofn(0,5,2); print "2 $hashfeld[1]{var2}[3]\n"; my $wert = $hashfeld[0]->{'var2'}[3]; print "$wert \n"; print pp(\@hashfeld), "\n\n"; sub dofn { my ($ivon, $ibis, $imal) = @_; my $hashfn; for (my $i = $ivon; $i < $ibis; $i++) { push @{$hashfn->{'var1'}}, $i*$imal; push @{$hashfn->{'var2'}}, $i*$imal*10.; push @{$hashfn->{'var3'}}, $i*$imal*20.; } return $hashfn; } $ perl pm_1195995.pl 1 30 2 60 30 [ { var1 => [0 .. 4], var2 => [0, 10, 20, 30, 40], var3 => [0, 20, 40, 60, 80], }, { var1 => [0, 2, 4, 6, 8], var2 => [0, 20, 40, 60, 80], var3 => [0, 40, 80, 120, 160], }, ]

      After making

      ...roboticus

      When your only tool is a hammer, all problems look like your thumb.

      Hello!

      Thanx to all of you. :)

      I am coming from Fortran and using Perl till now for not so a long time.

      Regards, buchi

Re: how to access array of hash with arrays?
by thanos1983 (Parson) on Jul 25, 2017 at 14:35 UTC

    Hello buchi2,

    Welcome to the monastery.

    It works almost as you have it, see sample of code bellow:

    #!/usr/bin/perl use strict; use warnings; use Data::Dumper; sub dofn { my %hashfn; my ($ivon, $ibis, $imal) = @_; for (my $i = $ivon; $i < $ibis; $i++) { push(@{$hashfn{'var1'}}, $i*$imal); push(@{$hashfn{'var2'}}, $i*$imal*10.); push(@{$hashfn{'var3'}}, $i*$imal*20.); } return \%hashfn; } my $hierhash_1 = dofn(0, 5, 1); # print "1 $hierhash_1->{'var2'}[3] \n"; push(my @hashfeld, $hierhash_1); my $hierhash_2 = dofn(0, 5, 2); # print "2 $hierhash_2->{'var2'}[3] \n"; push(@hashfeld, $hierhash_2); # print Dumper \@hashfeld; my $wert = $hashfeld[0]->{'var2'}[3]; print "$wert \n"; __END__ $ perl test.pl 30

    Update: I modified a bit your code. I would suggest a few points to read and it is up to you how you will proceed. I would suggest not to use subroutines/Prototypes use simply subroutines/Pass by Reference. Why? A fellow monk haukex wrote a recent post about it Fun with Prototypes.

    On Perl you do not need to pre-define your parameters you can use my straight on the parameter when you assign the value.

    Last point to mention, I would return a reference (hashref, arrayref, complexref) instead of the hash. Why? Read more here Subroutines: Returning a hash vs. hash reference.

    Hope this helps, BR.

    Seeking for Perl wisdom...on the process of learning...not there...yet!
      P.S.:

      Is it not necessary to give an & in front, if I call a subroutine?