anurag86
anurag86

Reputation: 1687

Not able to print value of this complex datastructure in perl

Question explained as comments in the code:

I have a following piece of code in which i am trying to make a hash in which the key itself is a reference to some other array.

my @arr1=(1,2,3,4,5,6,7,8,9,10);
my @arr2=(1001,1002,1003);



$FILES_1=\@arr1;
$num1=2;
$FILES_2=\@arr2;
$num2=4;

@FILES=($FILES_1, $FILES_2);
@NUMS=($num1,$num2);
    fun (\@FILES,\@NUMS);





sub fun{

    my ($rFILES,$rNUMS) = @_;

    print "\n --${$rFILES}[0]->[2]  \n "; # This is same as below
    print "\n --$rFILES->[0]->[2]  \n "; # This is same as above

    my %hash=();

    $hash{$rFILES->[0]} = $rNUMS->[0];   

    my $test = $rFILES->[0];
    print "\nTEST : $test->[1]";

    my @key = keys %hash;
    print "\nKey 1 = $key[0]";   # This prints scalar value as below
    print "\ntest  = $test ";   # This prints scalar value as above

    print "\nKey 1->[1] = ${$key[0]}->[1]";  #PROBLEM : THIS DOESNT PRINT SAME AS BELOW
    print "\ntest->[1]  = $test->[1] ";  #THIS PRINTS AS EXPECTED.
}

Output:

 --3

 --3

TEST : 2
Key 1 = ARRAY(0x1bbb540)
test  = ARRAY(0x1bbb540)
Key 1->[1] =
test->[1]  = 2 

Are we not supposed to keep a key of a hash as reference to some array? Why is the value "2" not printed?

Upvotes: 0

Views: 52

Answers (2)

Leeft
Leeft

Reputation: 3837

A hash key is always a string, you can't store a reference in there. I can't think of a reason you'd want this either.

You should really always use strict and use warnings. If you added those and declared your variables with my properly, you'd have gotten a warning:

Can't use string ("ARRAY(0x85e628)") as a SCALAR ref while "strict refs" in use

The syntax you're using:

${$key[0]}

says $key[0] is a reference to a scalar. It isn't, it's a string with the address of what the reference used to be, as you can't use a reference as a hash key they become strings.

Update:

You probably want something like this instead:

my @filegroups = (
    { number => 1, files => ['file1','file2'] },
    { number => 2, files => ['file3'] },
);

Accessed as:

foreach my $filegroup ( @$filegroups ) {
    print "my number is $filegroup->{number}\n";
    print "   and I have ".scalar( @{ $filegroup->{ files } } )." files\n";
}

If you need extra speed to access the structure by group number (don't bother unless you have hundreds of groups or thousands and thousands of accesses), index them:

my %filegroupindexes = map { $_->{ number } => $_ } values @$filegroups;

Then you can get to the group like this:

print "there are ".scalar( @{ $filegroupindexes{ 1 }->{ files } } )." files in group 1\n";

As a last hint, for printing complex data structures Data::Printer is my favourite:

use Data::Printer colored => 1;
p( @filegroups );

Upvotes: 3

Chankey Pathak
Chankey Pathak

Reputation: 21676

You need Tie::RefHash if you want to use references as hash keys.

Upvotes: 0

Related Questions