开发者

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

开发者 https://www.devze.com 2023-01-05 04:32 出处:网络
In perl, I\'m trying to build up a hash of a list of lists. It looks something like this: my %entries;

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开发者_如何学Go 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";
    }
}   


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";
    }
}


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.)


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.


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;
0

精彩评论

暂无评论...
验证码 换一张
取 消