Deleting and adding Hash and Array references in Perl

Question!

Continuing on from my previous question, I ran into another problem down the road. I realized not only should there be hashes within hashes, there can also be arrays within hashes. So the paths would be something like

one/two/three
one/two[]/three
one/two/four
one/two[]/four 

i.e. the hash is supposed to contain the array will always have a [] as its suffix. According to the script I'm using (slightly modified version of the answer of my previous question), the above paths would result in:

one => {
     two => {
         three => "",
         four => "",
     }
     two[] => [
         {
             three => "",
             four => "",
         }
     ]
}

The script I'm using is:

# !/usr/bin/perl

use Data::Dumper; 

sub insert {
  my ($ref, $head, @tail) = @_;
  if ( @tail ) { 
    if( $head !~ /^(.*)(\[\])$/ ) {
        insert( \%{$ref->{$head}}, @tail );
    } else {
        my %newhash = ();
        unshift(@{$ref->{$1 . $2}}, %newhash);
        insert( \%{$ref->{$1 . $2}[0]}, @tail );
    }
  } else {
    $ref->{$head} = '';
  }
}

my %hash;
chomp and insert \%hash, split( '/', $_ ) while <>;

print Dumper %hash;

What I'd like to do, is once I find two[], I'd like to delete two and add it to the array of two[] (if two exists) and then rename key two[] to two.

So the end result would look something like:

one => {
    two => [
        {
            three => "",
            four => "",
        },
        {
            three => "",
            four => "",
        }
    ]
}

So I tried adding checks within the if else for checking keys with or without [] suffixes but I got a range or errors like [$variable] is not a valid HASH reference, etc. How would one go about checking the type of the variable (eg $ref->{$head} is array?) and deleting and renaming keys of the hash efficiently?

Thanks.



Answers

I'm not sure by what logic you reach your expected output, but I can clarify the following:

  • You can check the type of the reference by using the ref function.
  • In your current code, $ref is treated as a hash reference in every single case. I can tell because you dereference it as a hash using the $ref->{...} syntax in every single clause of your if statements.
  • If I read you correctly, $1 . $2 should be the same thing as $head. I find it more clear as just $head.
  • Your unshift line vivifies $ref-
By : JB.


Okay, by all rights, this should suck AND not do what you want - But I spent the last hour trying to get it somewhat right, so I'll be damned. Each 'anything[]' is an array of two elements, each a hashref: One for elements that appear after a bare 'anything', and the second for elements appearing after a 'anything[]'. I probably should have used a closure instead of relying on that crappy $is_non_bracket variable -- I'll take another look in the morning when I'm less retarded and more ashamed of writing this.

I think that it's tail-call optimized (the goto

By : Hugmeir


This video can help you solving your question :)
By: admin