Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Push hash reference on array problem

by sxmwb (Pilgrim)
on May 23, 2007 at 19:52 UTC ( #617100=perlquestion: print w/replies, xml ) Need Help??
sxmwb has asked for the wisdom of the Perl Monks concerning the following question:

I know this is a simple problem and I am at the limits of my knowledge of utilizing hash references. I create a hash to hold the row elements that will populate an HTML::Template when I push the hash as a reference on the the array I end up with no values in the array.

Awaiting your guidance Mike


Update: Thanks to kyle I have the solution. I will also try to reduce code sample in the future.
Statement that works:
push (@dfdata_out,{device => $dfdata_row{'device'}, 'mount' => $dfdata +_row{'mount'}, 'size' => $dfdata_row{'size'}, 'tuse' => $dfdat +a_row{'tuse'}, 'yuse' => $dfdata_row{'yuse'}, 'ychange' => $df +data_row{'ychange'}, 'wuse' => $dfdata_row{'wuse'}, 'wchange' => $df +data_row{'wchange'}, 'muse' => $dfdata_row{'muse'}, 'mchange' => $df +data_row{'mchange'}, 'yruse' => $dfdata_row{'yruse'}, 'yrchange' => +$dfdata_row{'yrchange'}});

Statement that does not work but should:
push @dfdata_out, (\%dfdata_row);


Full code below:
#!/usr/bin/perl use warnings; use strict; use DBI; use HTML::Template; use Tie::IxHash; use Date::Calc qw(Add_Delta_YM Add_Delta_Days Today Month_to_Text); my ($df_date,$df_device,$df_size, $df_used, $df_available, $df_used_pe +rcent, $df_mounted); # Ref Hashes to hold df_data for a date indexed by mount point my %df_data; # Flags for no values found - set to false, if true no records found # ignore compare processing against that time segment. my ($tdf_flag, $ydf_flag, $lwdf_flag, $lmdf_flag, $lydf_flag) = 0; my (@today, @yesterday, @last_week, @last_month, @last_year); my ($tyear, $tmonth, $tday) = @today = Today(); # set values and array my ($yyear, $ymonth, $yday) = @yesterday = Add_Delta_Days(@today, -1); my ($lwyear, $lwmonth, $lwday) = @last_week = Add_Delta_Days(@today, - +7); my ($lmyear, $lmmonth, $lmday) = @last_month = Add_Delta_YM(@today, 0, + -1); my ($lyyear, $lymonth, $lyday) = @last_year = Add_Delta_YM(@today, -1, + 0); my $ydf_date = $yyear . "-" . Month_to_Text($ymonth) . "-" . $yday; my $lwdf_date = $lwyear . "-" . Month_to_Text($lwmonth) . "-" . $lwday +; my $lmdf_date = $lmyear . "-" . Month_to_Text($lmmonth) . "-" . $lmday +; my $lydf_date = $lyyear . "-" . Month_to_Text($lymonth) . "-" . $lyday +; $df_date = $tyear . "-" . Month_to_Text($tmonth) . "-" . $tday; my @dfdata_out = (); my %dfdata_row; my %date_hash = ( 'today' => [$df_date, $tdf_flag, 'tuse', 'tchange'], 'yesterday' => [$ydf_date, $ydf_flag, 'yuse', 'ychange +'], 'last week' => [$lwdf_date, $lwdf_flag, 'wuse', 'wchan +ge'], 'last month' => [$lmdf_date, $lmdf_flag, 'muse', 'mcha +nge'], 'last year' => [$lydf_date, $lydf_flag, 'yruse', 'yrch +ange']); my $dbname = "/home/mbates/data/df_data.sqlite3"; if ( !-e $dbname ) { print "\n File $dbname does not exist, exiting program.\n"; exit; } my $dbconn = "dbi:SQLite:" . $dbname; my $sth; my $dbh = DBI->connect( $dbconn, {RaiseError=>1, ShowErrorStatement=>1, PrintError=>1}) or die "Can't make connection to database: $dbname\n"; eval { $sth = $dbh->prepare('SELECT * FROM df_data WHERE df_date = ?'); }; if ( $@ ) { print "\nError in the database: $@\n"; exit; } for my $key ('today', 'yesterday', 'last week', 'last month', 'last ye +ar') { eval { $sth->execute($date_hash{$key}[0]); $df_data{$key} = $sth->fetchall_hashref(['df_device']); }; if ( $@ ) { print "\nError in the database: $@\n"; exit; } if ($sth->rows == 0) { $date_hash{$key}[1] = 0; # 1 means no records so is false #print "No values match date of $df_date \n"; } else { $date_hash{$key}[1] = 1; } } $dbh->disconnect; my $template = HTML::Template->new(filename => '/templates/df_report.t +mpl'); $template->param(RDATE => $df_date); for my $df_hkey (sort keys %{ $df_data{'today'} } ) { # Loop on Devi +ce for today # Get base data for today $dfdata_row{'device'} = $df_data{'today'}{$df_hkey}{ 'df_device' } +; $dfdata_row{'mount'} = $df_data{'today'}{$df_hkey}{ 'df_mounted' } +; $dfdata_row{'size'} = calc_size_pretty($df_data{'today'}{$df_hkey} +{ 'df_size' }); my $suse = calc_size_pretty($df_data{'today'}{$df_hkey}{'df_used'} +); my $savail = calc_size_pretty($df_data{'today'}{$df_hkey}{'df_avai +lable'}); $dfdata_row{'tuse'} = $suse . "/" . $savail; for my $df_hashkey ('yesterday', 'last week', 'last month', 'last +year') { # if $df_hashkey[1] has a valid value setup information otherw +ise set to NA if ( $date_hash{$df_hashkey}[1] ) { $dfdata_row{$date_hash{$df_hashkey}[2]} = 'BA'; $dfdata_row{$date_hash{$df_hashkey}[3]} = 'BA'; } else { $dfdata_row{$date_hash{$df_hashkey}[2]} = 'NA'; $dfdata_row{$date_hash{$df_hashkey}[3]} = 'NA'; } } push (@dfdata_out,{device => $dfdata_row{'device'}, 'mount' => $df +data_row{'mount'}, 'size' => $dfdata_row{'size'}, 'tuse' => $dfdat +a_row{'tuse'}, 'yuse' => $dfdata_row{'yuse'}, 'ychange' => $df +data_row{'ychange'}, 'wuse' => $dfdata_row{'wuse'}, 'wchange' => $df +data_row{'wchange'}, 'muse' => $dfdata_row{'muse'}, 'mchange' => $df +data_row{'mchange'}, 'yruse' => $dfdata_row{'yruse'}, 'yrchange' => +$dfdata_row{'yrchange'}}); #push @dfdata_out, (\%dfdata_row); %dfdata_row = (); } $template->param( { rows => \@dfdata_out } ); print $template->output(); sub calc_size_pretty { my ($csize) = @_; my $new_size; if ($csize >= 1024000) { return (sprintf ("%.1f", (($csize/(1024*100)) + .05)) . "G"); } else { return (sprintf ("%.1f", (($csize/1024) + .05)) . "M") } }

Replies are listed 'Best First'.
Re: Push hash reference on array problem
by kyle (Abbot) on May 23, 2007 at 20:14 UTC
    #push @dfdata_out, (\%dfdata_row); %dfdata_row = ();

    What happens here is that you push into @dfdata_out a reference to the hash %dfdata_row, and then you empty the hash. After that, the reference in @dfdata_out is the same reference pointing to an empty hash. What you probably want to do is:

    push @dfdata_out, { %dfdata_row }; %dfdata_row = ();

    This is effectively the same as what's working for you now. It copies the old hash to a new (anonymous) hash and pushes a reference to the copy on the list.

    You might want to have a look at perlreftut for more.

Re: Push hash reference on array problem
by imp (Priest) on May 23, 2007 at 20:15 UTC
    In the loop you are pushing a reference to the same hash onto the list repeatedly, then deleting the data in that hash at the end of the loop.

    Declare %dfdata_row in the body of the loop, and don't assign () to it after pushing it onto the list.

      Try it slightly modified:
      push (@dfdata_out, \%dfdata_row);
Re: Push hash reference on array problem
by thezip (Vicar) on May 23, 2007 at 20:13 UTC
    Right after you fill the %dfdata_row hash, try using Data::Dumper on it, like:
    use Data::Dumper; print Dumper(\%dfdata_row); exit(0); ... the rest of your code ...

    What do you see?


    Where do you want *them* to go today?
Re: Push hash reference on array problem
by FunkyMonk (Chancellor) on May 23, 2007 at 20:10 UTC
    You really need to trim that code down to something much smaller that still demonstrates your problem.
    Statement that does not work but should:

    push @dfdata_out, (\%dfdata_row);
    Well, you're expecting an array of hashrefs and that's exactly what your push should do (the parentheses are unnecessary, btw).

    Are you sure %dfdata_row contains what you think it does? Data::Dumper can help you determine its contents easily.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://617100]
Approved by thezip
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (6)
As of 2018-07-21 15:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    It has been suggested to rename Perl 6 in order to boost its marketing potential. Which name would you prefer?















    Results (449 votes). Check out past polls.

    Notices?