简体   繁体   中英

Dereferencing an array reference from a nested Perl hash

I hope I've stated that subject correctly. I have a hash of hashes that I've built from reading a file. The outer hash is groups, then the inner hash is parameters within that group. Each parameter value can either be a scalar or array, and the arrays can start at either zero or one.

I've written a subroutine that returns the value of a parameter. The calling function has to figure out whether the returned value is a scalar or an array. Works fine for scalars. Returns a reference to an array for array values (looks like ARRAY(0x004f00) ). Using Data::Dumper spits out data that looks like an array, but I can't figure out how to dereference it in the code. Can someone point to what I'm doing wrong?

%HoH = (
    flintstones => {
        husband     => "fred",
        possessions => [ undef, "car", "record player", "rock" ],
        pal         => "barney",
        pets        => [ "bird", "dinosaur" ],
    },
);

get_value("possessions");

sub get_value {

    my $what_i_want = shift;

    @groups = keys(%HoH);

    foreach my $group ( @groups ) {

        foreach my $param ( keys( %{ HoH {group} } ) ) {

            if ( $param eq $what_i_want ) {
                return $HoH{$group}{$param};
            }
        }
    }
}

The caller assigns the return value to an array, @return , so in the case of a scalar it should put the value in $return[0] .

In the case of an array, it should populate the array. When I call Dumper , it prints out scalars in single quotes and arrays in square brackets, as it should. However, when I use scalar(@return) to check the size of the array, it returns 1.

I've tried dereferencing the return statement using square brackets at the end to see if I could even get a scalar returned, but no luck.

You don't show the subroutine being called in context, but a quick fix would be to put this after the call

@return = @{ $return[0] } if ref $return[0]



Update

You're missing the point of hashes. You can access the correct element of the parameter hash by using $what_i_want as a hash key

I suggest you change your subroutine code to look like this

for my $group ( keys %HoH ) {

    my $ret = $HoH{$group}{$what_i_want};

    return unless defined $ret;
    return ref $ret ? @$ret : $ret;
}

That way it will never return a reference



Update 2

Here's your complete program modified as I suggested

use strict;
use warnings 'all';

my %HoH = (
    flintstones => {
        husband     => "fred",
        possessions => [ undef, "car", "record player", "rock" ],
        pal         => "barney",
        pets        => [ "bird", "dinosaur" ],
    },
);

my @return = get_value('possessions');

use Data::Dump;
dd \@return;

sub get_value {

    my ($wanted) = @_;

    for my $group ( keys %HoH ) {

        my $ret = $HoH{$group}{$wanted};

        if ( defined $ret ) {
            return ref $ret ? @$ret : $ret;
        }
    }

    return;
}

output

[undef, "car", "record player", "rock"]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM