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

need just a quick push to help me get going into passing a multi dimensional hash into a sub...thanks in advance

tim = 40 , 70, 50, 80 john = 98, 97 , 100, 89 eden = 87, 56, 89, 97 pepe = 93 ,91, 94, 90 leah = 100, 99, 99, 100 tony = 89, 94, 100, 89 matt = 68, 70, 75, 73

maybe show me how to pass it by value and ref

use strict; use warnings; use Data::Dump qw(dump); use autodie; my %ave; open my $in,'<', "testscores.txt"; while (<$in>){ my ($name, $score) =split /[\s=s,]+/; for (0..3){ $ave{$name}[$_]=$score; } } #dump \%ave; get_ave(\%ave); #get it by hash_ref my %hash_ref; #why do I have to declare ? sub get_ave{ my $hash_ref =@_; #declared here too? my %hash=%$hash_ref; dump \%hash; #dump \%hash_ref; }

Replies are listed 'Best First'.
Re: passing multi dimensional hashes into a sub
by Laurent_R (Canon) on Sep 17, 2015 at 07:36 UTC
    You can actually pass the hash of arrays by value without any problem, as if it were a single-dimension hash (in a sense it is a simple hash in which the values happen to be array refs):
    $ perl -MData::Dumper -e ' my %h = (tim => [ 4, 7], joan => [5, 8], fr +ed => [8, 3]); > proc(%h); > sub proc { > my %h_sub = @_; > print Dumper \%h_sub; > }' $VAR1 = { 'tim' => [ 4, 7 ], 'joan' => [ 5, 8 ], 'fred' => [ 8, 3 ] };
    Now, of course, this implies copying the (top level) hash. If it is large, you might want to use passing by ref to avoid the overhead of making such a copy. But the structure of the data does not prevent you from passing the hash by value.
Re: passing multi dimensional hashes into a sub
by poj (Abbot) on Sep 17, 2015 at 06:46 UTC
    #!perl use strict; use warnings; use autodie; use Data::Dump qw(dump); my %data; #open my $in,'<', "testscores.txt"; while (<DATA>){ my ($name, @score) = split /[\s=,]+/; $data{$name} = \@score; } dump \%data; my $avg = get_avg(\%data); dump $avg; sub get_avg { my ($hash_ref) = @_; my %avg = (); for my $name (sort keys %$hash_ref){ my $sum = 0; my $count = 0; for my $score (@{$hash_ref->{$name}}){ $sum += $score; ++$count; } $avg{$name} = $sum/$count; } return \%avg; } __DATA__ tim = 40 , 70, 50, 80 john = 98, 97 , 100, 89 eden = 87, 56, 89, 97 pepe = 93 ,91, 94, 90 leah = 100, 99, 99, 100 tony = 89, 94, 100, 89 matt = 68, 70, 75, 73
    poj

      the reason I asked previously about hash format was to try to understand when %hash should be used rather than %hash_ref ($hash_ref->{$key})

      when wrongly used, I get an error that reads Global explicit package... and need to declare it...I seem to get a lot so i need to understand where to use one or the other

      ergo, the reason why I asked for you to explain how you go about deciding which to use %hash vs %hash_ref...hoping to get some insight into this!

      yes, I've read up on this subject and still confused

        Never use %hash_ref, its not a "ref"erence, its a hash, so don't call it a reference

        Also never use %hash either, the % part tells you its a hash, the "hash" part is supposed to describe whats inside this dictionary, which "hash" doesn't do

        Outside of an introduction to hashes never use hash unless you're storing md5sum or some such, in which case you still shouldn't use it, unless the type of hash isn't set (can be md5 or sha1 or ... so the generic hash fits)

        See age of peter, sum of bob and Subroutines: Returning a hash vs. hash reference and free book Modern Perl

        So taking all this into account

        Do you see when you would use it %Scores versus $ScoresRef?

        So, we use hash references to save memory,

        and we use hashes to avoid typing  ->

        once you get used to the idea of typing  -> , you use hashes to avoid scaring noobs :)

      can you explain the format you chose to use @{$hash_ref->{$name}}

      it's kind of confusing to see how the hash_ref (arrays) is going through the list in the array for me

      could you have used any other from to point to the values of each student?

      something like hash_ref{$name}[ 0..2] and use a loop to get the index to move across all three values

      do you think it'll work if i compose a loop like in the format above?

Re: passing multi dimensional hashes into a sub
by locked_user sundialsvc4 (Abbot) on Sep 17, 2015 at 11:54 UTC

    Remember, Perl really has only three data structures:   hashes, arrays, and lists.   Each can only contain scalars ... of the same or different types.   But, a reference is a type of scalar, which can point to anything, and it is by this mechanism that Perl is able to create arbitrary data structures.   Thus, from Perl’s point of view, you are passing the sub “a reference to a hash (a ‘hashref’), each bucket of which contains a reference to an array (an ‘arrayref’) of integers.”