Search code examples
perlperl-data-structures

Accessing hash reference in perl


I am wondering if the following is possible to do in perl. It will save 40-50 lines of code.

I have a hash data structure like following:

hash_Ref->{a}->{b}->{c}->{d}->{e}->{'count'}=30

I am wondering is there a way I can do the following:

my $hash_ref_1 = ash_Ref->{a}->{b}->{c}->{d};

and then use:

$hash_ref_2->{e}. 

So in summary I want to store hash reference till a point "x" in the hierarchy in a variable and then access the reference which the point "x" points to. I think this is more clear in the example above.

More details

I tried couple of things but doesnt seem to work for me. I am copying the code but not all the things I tried to copy hash. Also the output I am getting is something like this

 $VAR1 = {
          'e' => {
                   'count' => 2
                 },
          'c' => {
                   'count' => 2
                 },
          'a' => {
                   'count' => 2
                 },
          'b' => {
                   'count' => 2
                 },
          'd' => {
                   'count' => 2
                 }
        };

where I would expect something like this:

'a' => { 'count' => 2, 'b' => { 'count' => 2, 'c' => ......} }  

Here's some code I used:

use strict;
use Data::Dumper;

my @array1 = ('a','b','c','d','e');
my @array2 = ('a','b','c','d','e');
my $hash;

 build_hash(\@array1);
 build_hash(\@array2);


sub build_hash {

    my @array = @{shift @_};

    my $hash_ref;

    for ( my $i =0 ;  $i < scalar @array ; $i++ ){

        print "$i \t $array[$i] \n";
         if ( exists $hash->{$array[$i]} ){

            $hash->{$array[$i]}->{'count'}++;
        }

        else{

            $hash->{$array[$i]}->{'count'}=1;
        }
    }
    print Dumper($hash);

}

I want to build a hierarchy of hash references based on the elements in the perl in the sequential order and possibly using one loop like I have tried to do in the sample code.

Thanks! -Abhi


Solution

  • # 'a' => { 'count' => 2, 'b' => { 'count' => 2, 'c' => ......} }
    
    sub build_hash {
        $_[0] ||= {};
        my $hash = shift;
        for (@_) {
            $hash = $hash->{$_} ||= {};
            ++$hash->{count};
        }
    }
    
    build_hash($hash, @array1);
    build_hash($hash, @array2);
    

    If you wanted to use autovivification, you could write it as follows:

    sub build_hash {
        my $p = \shift;
        for (@_) {
            $p = \( $$p->{$_} );
            ++$$p->{count};
        }
    }
    
    build_hash($hash, @array1);
    build_hash($hash, @array2);
    

    See also: Data::Diver