Add array to hash in perl

Viewed 376

I try to add array in hash.

if ( not exists $hashtime{ $arr[0] }{ $date }{ $hour }{ $min } ) {
    print "$min not exist";
    $hashtime{ $arr[0] }{ $date }{ $hour }{ $min } = [ $sec ];
    $create++;
};

And received the error:

Not a HASH reference at ./sort_log_by_ip.pl line 63, line 1.

Why is this code wrong?

In perldoc perldsc I see this construction, and I'm using something similar:

while ( <> ) {
     next unless s/^(.*?):\s*//;
     $HoA{$1} = [ split ];
}

Update

Code before:

if ( not exists $hashtime{ $arr[0] } ) {
    $hashtime{ $arr[0] } = ( $date => { $hour => { $min => [ $sec ] } } );
    $create++; 
    print "create for IP: $arr[0]\n";
}

if ( not exists $hashtime{ $arr[0] }{$date} ) {
    $hashtime{ $arr[0] }{ $date } = ( $hour => { $min => [ $sec ] } );
    $create++;
    print "create for IP: $arr[0] DATE: $date\n";
}

if ( not exists $hashtime{ $arr[0] }{$date}{$hour} ) {
    $hashtime{ $arr[0] }{ $date }{ $hour } = ( $min => [$sec] );
    $create++;
    print "create for IP: $arr[0] DATE: $date HOUR: $hour\n";
}
1 Answers

You are using a list ( ) instead of a hash reference { }, in all if blocks.

When you say

$hashtime{$arr[0]} = ( $date => { $hour => { $min => [$sec] } } );

because of LIST ( ) being evaluated in scalar context what happens is equivalent to

$hashtime{$arr[0]} = ( $date, { $hour => { $min => [$sec] } } );

ending up as

$hashtime{$arr[0]} = { $hour => { $min => [$sec] } };

since the , operator evaluates and discards operands one at a time, returning the last one.

The next if goes similarly and you then have either of (or both)

$hashtime{$arr[0]}{$date}{$min}{[$sec]}
$hashtime{$arr[0]}{$hour}{$min}{[$sec]}

However, the code that draws the error

if (not exists $hashtime{$arr[0]}{$date}{$hour})

needs a hashref at both $arr[0] and {$date}, while it clearly doesn't have both.


In both if blocks you need to assign a hash reference, obtained using { }

$hashtime{$arr[0]} = { $date => { $hour => { $min => [$sec] } } };

and

$hashtime{$arr[0]}{$date} = { $hour => { $min => [$sec] } };

as well as in the last if block.


Please indent your code properly. It is very hard to work with it the way it was posted.

Related