Search code examples
arraysperlhashreferencesubroutine

How to pass value of a hash of arrays into a subroutine?


I have a hash of arrays. I'm trying to do the following: as I'm looping through the keys of the hash, I would like to pass the value of the hash (in this case the array) into a subroutine.

Once I'm in the subroutine, I'd like to do a bunch of calculations with the array including take the average of the numeric values in the array. Lastly return a value based on the calculations.

Here's a minimal representation of what I have:

#!/usr/bin/perl
use warnings; use strict;
use List::Util qw(sum);

%data_set = (
    'node1' => ['1', '4', '5', '2'],
    'node2' => ['3', '2', '4', '12'],
    'node3' => ['5', '2', '3', '6'],
    );

foreach my $key ( keys %data_set ) {
    foreach ( @{$data_set{$key}} ) {
        my @array = split;   # it's not letting me 
        calculate(\@array);   ### I'm getting the error here!!
    }
}

sub calculate{
    my @array = @{$_};
    my $average = mean(\@array);
    # do some more calculations
    return; # return something
}

# sum returns the summation of all elements in the array
# dividing by @_ (which in scalar content gives the # of elements) returns
# the average
sub mean{
    return sum(@_)/@_;
}

Quick clarification: On the first iteration node1, I'd like to pass the array '1', '4', '5', '2' into the subroutine.

I think for my purposes this might be a bit more efficient than passing a reference to the hash of arrays into each subroutine. What do you guys think? In any case, can you guys help me figure this out? Any suggestions are appreciated. thanks


Solution

  • I think you are a bit confused about when you need to reference and dereference variables as well as what you are passing, where.

    Lets look at this closer,

    foreach my $key ( keys %data_set ) {
        foreach ( @{$data_set{$key}} ) {
            my @array = split;   # it's not letting me 
            calculate(\@array);   ### I'm getting the error here!!
        }
    }
    

    You loop over the hash to get the keys, but then you use them to access the values to dereference the arrays and split each array into a single element array (of a string). Then you pass a reference to that 1-element array to calculate. Basically, you are doing too much work if the only thing that you want to do is pass each value of the hash (the arrays) into the calculate subroutine. Try something like this:

    foreach my $key (keys %data_set){
        calculate($data_set{$key}); # This is already a reference to an array
    }
    

    Additionally, in calculate you need to change my @array = @{$_}; to either my @array = @{$_[0]}; or my @array = @{(shift)};