in reply to Brain muchly befuddled by nested hashes

I think there has been some confusion caused by one of the variable names you have chosen. You use substr to pull a date and time string from your data line. You then use substr again to isolate parts of that string. One of these you call $date but it is, in fact, only the day of the month; perhaps something like $mday would have been a more descriptive choice.

Others have addressed the issue of the fat comma (=>) in your hash key and the resultant odd characters in your keys. I concatenate the text you use with the day or hour value to form the keys by using interpolation in a double-quoted string. Cristoforo thought at a regular expression would be a good choice for extracting the date and time information you require. I would agree but, without seeing your data, I do not know whether there is similarly formatted date & time information earlier in each line. Therefore, I use a combination of substr and a regular expression, using captures in the match to pull out fields of interest (see Extracting matches, perlretut and perlre). Cristoforo also advocated the use of sprintf to format your hours along with a solution using two hashes rather than your one. My code below uses just the one hash and, as ptoulis recommends, avoids some of the redundancy in your data structure. I also avoid some typing in each nested foreach by assigning the hash reference I'm interested in within the structure to a lexical scalar scoped to the loop, see perlreftut and perlref. When incrementing the hourly count for the bottom or top of the hour I use a ternary to decide which hash element to address, see Conditional Operator in perlop.

use strict; use warnings; my %signIn = (); while( <DATA> ) { my $dateStr = substr $_, 42, 17; next unless my( $mday, $hr, $min, $ampm ) = $dateStr =~ m{\d\d/(\d\d)/\d{4}\s+(\d{1,2}):(\d\d)(a|p)}; $hr = 0 if $hr == 12; $hr += 12 if $ampm eq q{p}; $hr = sprintf q{%02d}, $hr; my $mdayKey = qq{DayOfMonth$mday}; my $hrKey = qq{HourSignIn$hr}; $signIn{ $mdayKey }->{ TotalPerDay } ++; $signIn{ $mdayKey }->{ $hrKey }->{ TotalPerHour } ++; $signIn{ $mdayKey }->{ $hrKey }-> { $min < 30 ? q{HalfHour00} : q{HalfHour30} } ++; } foreach my $mdayKey ( sort keys %signIn ) { my $rhDaily = $signIn{ $mdayKey }; print qq{$mdayKey\n}, qq{ TotalPerDay - $rhDaily->{ TotalPerDay }\n}; foreach my $hrKey ( sort grep m{^Hour}, keys %{ $rhDaily } ) { my $rhHrly = $rhDaily->{ $hrKey }; print qq{ $hrKey\n}, qq{ TotalPerHour - $rhHrly->{ TotalPerHour }\n}, qq{ HalfHour00 - }, exists $rhHrly->{ HalfHour00 } ? qq{$rhHrly->{ HalfHour00 }\n} : qq{0\n}, qq{ HalfHour30 - }, exists $rhHrly->{ HalfHour30 } ? qq{$rhHrly->{ HalfHour30 }\n} : qq{0\n}; } } __END__ 0123456789012345678901234567890123456789 06/05/2008 8:31a&&&&&&& abcdefghijabcdefghijabcdefghijabcdefghij 06/07/2008 12:15p&&&&&&& 0123456789012345678901234567890123456789 06/05/2007 1:46p&&&&&&& abcdefghijabcdefghijabcdefghijabcdefghij 06/05/2008 12:49p&&&&&&& This is a line of rubbish that doesn't match the data requirements 0123456789012345678901234567890123456789 06/05/2008 2:24a&&&&&&& abcdefghijabcdefghijabcdefghijabcdefghij 06/05/2007 11:09a&&&&&&& 0123456789012345678901234567890123456789 06/12/2007 12:17a&&&&&&& abcdefghijabcdefghijabcdefghijabcdefghij 06/05/2008 11:09p&&&&&&& 0123456789012345678901234567890123456789 06/05/2008 11:42p&&&&&&&

The output.

DayOfMonth05 TotalPerDay - 7 HourSignIn02 TotalPerHour - 1 HalfHour00 - 1 HalfHour30 - 0 HourSignIn08 TotalPerHour - 1 HalfHour00 - 0 HalfHour30 - 1 HourSignIn11 TotalPerHour - 1 HalfHour00 - 1 HalfHour30 - 0 HourSignIn12 TotalPerHour - 1 HalfHour00 - 0 HalfHour30 - 1 HourSignIn13 TotalPerHour - 1 HalfHour00 - 0 HalfHour30 - 1 HourSignIn23 TotalPerHour - 2 HalfHour00 - 1 HalfHour30 - 1 DayOfMonth07 TotalPerDay - 1 HourSignIn12 TotalPerHour - 1 HalfHour00 - 1 HalfHour30 - 0 DayOfMonth12 TotalPerDay - 1 HourSignIn00 TotalPerHour - 1 HalfHour00 - 1 HalfHour30 - 0

I hope you find these ideas useful.

Cheers,

JohnGG

Replies are listed 'Best First'.
Re^2: Brain muchly befuddled by nested hashes
by WartHog369 (Novice) on Nov 26, 2008 at 06:04 UTC
    
    To All who have contributed:
    *THE* 'aah-hhaa' moment is gathering steam in the hinterlands of my brain
    and I expect to encounter it soon.
    
    I believe my basic problem (area of misunderstanding) is that I am conflating
    Perl's keys and values for hashes with how I would work with (program/manipulate)
    datafields/sets/databases in another environment.  Perl's hashes, I perceive, are
    a slightly different animal than what I have used in the past.
    
    For now though, THANK YOU, for:
    ysth:   Variables don't interpolate in single quotes.
            setting $Data::Dumper::Useqq=1 when examining your data
    
    graff:   Something like simple concatenation or string interpolation would be clearer
            ($hash{'string'.$num} or $hash{"string$num"}). (ME: You share in the comment below
            to -johngg- with regard to 'interpolation')
    
    ptoulis: noted before, {[ME: but still having trouble with the 'fat comma' and its' documentation)
    
    Cristoforo: "but here is my take...there are 2 hashes" - (ME: I was tring to be 'simple' and
                 stay with only one hash.  Also, regEx's are still a bane to me (apologies to Friedl
                 and Goyvaerts))
    
    wol:    avoid using a => in a hash key, Welcome to Perl :-) (ME: you have a wicked sense of humor - no?)
    
    johngg: I think there has been some confusion caused by one of the variable names you have chosen. (ME: Concur)
            the issue of the fat comma (=>) in your hash key (ME: Yes, I was tring to define the hash key
            "on the fly" with concatenation and should have been using "interpolation" as you have suggested)
            see perlreftut and perlref.(ME: references I dig (60's lingo))
            (ME: "The Output" that you present appears to be exactly what I was trying to accomplish!)
    
    For ALL: my sincerest thanks for your time and effort on my part, and now that I not as "new to Perl" as
    I 'once' was, perhaps someone may present a thorny problem for which I may be of some assistance.  Thank You.
    Thomas