0

I have built a hash containing arrays of arrays, let's call it %hash_multidim, such that the output from Data::Dumper looks like so:

      'Key1' => [
                   [
                     '-3.81',
                     '-1.91',
                     '-1.86',
                     '-1.70'
                   ],
                   [
                     '1.35',
                     '1.04',
                     '-1.01',
                     '-2.69'
                   ]
                 ],
      'Key2' => [
                    [
                      '-1.63'
                    ],
                    [
                      '-1.17'
                    ]
                  ],

Now, I would like to access and perform manipulations on the bottom-most level in this structure. For example, for 'Key1' I want to find the mean of the in row 1 (aka the mean of the array at [0]). Using List::Util qw(sum), I have written a subroutine called mean:

sub mean {
    return sum(@_)/scalar(@_);
}

However, if using the subroutine, eg:

my $test = mean($hash_multidim{Key1}[0]);
print $test;

I do not get what I expect. In fact, I get:

43678288

Where did I go wrong? If I try to evaluate the result of

$hash_multidim{Key1}[0]

everything looks kosher. E.g.,

@test2 = $hash_multidim{Key1}[0];
print Dumper(\@test2);

produces this output:

$VAR1 = [
          [
            '-3.81',
            '-1.91',
            '-1.86',
            '-1.70'
          ]
        ];

2 Answers 2

4

$hash_multidim{Key1}[0] is an array reference, but mean expects a list. So you just need to "dereference" it. The syntax is a little tricky, but it is

my $test = mean( @{$hash_multidim{Key1}[0]} );
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks! My intuition was that it was a problem of dereferencing, but I messed up the syntax when attempting to fix it. I tend to panic when dereferencing part of a multidimensional data structure. Any tips (other than experience) or heuristics for knowing how/when to dereference? Actually, I'm fairly sure I already know when, but the how (for complex situations) often leaves me befuddled even after reading through perldocs.
If your expression starts with $, then you always have a scalar (which could be a reference to an array or hash). If it starts with @ or %, then it's an array or hash.
3

$hash_multidim{Key1}[0] is a scalar whose value is a reference to an array. You're passing that single scalar to mean when you mean to pass the values of the elements of the referenced array.

my $test = mean( @{ $hash_multidim{Key1}[0] } );


Note: The division operator cannot divide by a list, only by a number. As such, it imposes a scalar context on its operands. Your use of scalar is superfluous. You could simply use

sub mean { sum(@_)/@_ }

1 Comment

Thanks for the tip re: division by lists! I thought that I could write it your way, but I don't always program in Perl and I like to be explicit for myself (so I don't panic when I go back to my code later).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.