Tutorial :Creating a hash string => list of lists, what am I doing wrong?



Question:

In perl, I'm trying to build up a hash of a list of lists. It looks something like this:

my %entries;  while(<>)  {      if(/complicated regex ommitted/)      {          my @entry = ($2, $3, $4);          if(exists $entries{$1})          {              push @{$entries{$1}}, @entry;          }          else          {              $entries{$1} = @entry;          }  }  

The resulting hash has all of the keys I expect, but the value "list of lists" isn't being built up correctly. What am I doing wrong?

Edit: Maybe there is something wrong with how I'm trying to access the resulting hash.. Here is that code

foreach $key (keys %entries)  {      my $size = {@entries{$key}};      # just says "HASH(0xaddress)"?      print "$key: $size\n";       foreach(@{entries{$key}})      {          # loop just goes through once, prints out just " : "          print "\t$_[0]: $_[1] $_[2]\n";      }  }     


Solution:1

Perl has a feature called autovivification that makes scaffolding spring to life when you need it. This keeps your code simple:

my %entries;  while(<>)  {      if (/complicated regex ommitted/)      {          my($key,@entry) = ($1, $2, $3, $4);          push @{ $entries{$key} }, \@entry;      }  }  

There's no need to check whether this is the first group of entries for a given key.

To dump the contents of %entries, use code that resembles

foreach my $key (sort keys %entries)  {      my $n = @{ $entries{$key} };      print "$key ($n):\n";        foreach my $l (@{ $entries{$key} })      {          print "\t$l->[0]: $l->[1] $l->[2]\n";      }  }  


Solution:2

You're pushing a list, rather than a listref. Try:

push @{$entries{$1}}, \@entry;  

(You don't need to check for the existence of the field first.. if it didn't already exist, it will be created when you push to it, through the wonders of autovivication.)


Solution:3

You need to push a reference onto the list, otherwise the lists just get appended so that you get a simple list (see the manual on push). "List of list" is always a "list of references to lists" in Perl.


Solution:4

while ( <> ) {    if ( / (r) (e) (g) (e) x /x ) {      push @{ $entry{ $1 } }, [ $2, $3, $4 ];  }  }  

or in 1 line:

/(r)(e)(g)(e)x/ and push @{$entry{$1}}, [$2, $3, $4] while <>;  

and to show them:

use Data::Dumper;    print Dumper \%entry;  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »