Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number

Re^3: Perl Hashes, keys under keys (I think)?

by mmartin (Monk)
on Sep 20, 2011 at 20:09 UTC ( #927014=note: print w/replies, xml ) Need Help??

in reply to Re^2: Perl Hashes, keys under keys (I think)?
in thread Perl Hashes, keys under keys (I think)?

Hey hbm,

I think I got it working correctly. All's I really had to do was add a couple of lines (i.e. add $count++, as well as a "else" clause, etc...).

Here's what I got:

if ($fields[5] =~ /(OWNER|WAITING)/) { $x++; $state = $1; if ($state eq 'OWNER') { $count = 0; } if ($state eq 'WAITING') { $state .= "-$count"; $count +++; } @fields = split " ", $temp[$x]; print "$state --- @fields\n"; #Add record to hash based on RECORD_ID $records{"$fields[1]"}{ $state } = { USER => "$fields[5]", FILENAME => "$fields[0]", PID => "$fields[6]", TIME => "$fields[9]", DATE => (join " ", "$fields[10] $fields[11]"), ELAPSED => [] }; #Increment to Next Line $x++; } else { $records{"$fields[1]"}{ "WAITING-$count" } = { USER => "$fields[5]", FILENAME => "$fields[0]", PID => "$fields[6]", TIME => "$fields[9]", DATE => (join " ", "$fields[10] $fields[11]"), ELAPSED => [] }; $count++; $x++; }

Thanks Again,


Replies are listed 'Best First'.
Re^4: Perl Hashes, keys under keys (I think)?
by hbm (Hermit) on Sep 21, 2011 at 12:36 UTC


    Consider reading your data one line at a time, rather than slurping into an array and manipulating $x.

    Also, here:

    DATE => (join " ", "$fields[10] $fields[11]"),

    The double-quotes on the right side bind the tenth and eleventh fields into a single string, which you then join(?) with a space. Joining a single item doesn't do anything; you can simply do:

    DATE => "$fields[10] $fields[11]"

      Hey hbm, thanks for the reply.

      I tried reading the data into the hash at first but it was just confusing the crap out of me (trying to use @_ or $_ and also $line) so I did the array thing just to get myself started. Once I get more comfortable with hashes, most likely by the end of this, I will probably go back and change it to what you suggested.

      haha Yeah your right, I guess it is pointless to use "join" when only joining 2 elements. Good point, thanks.

      I was working on this thing below that I am kinda stuck on. Maybe you could see what I am not doing right.
      What I want to do is: I have this new SUB, also a new array (@colLens used this method before with a 2D-Array and it worked good). @colLens has 0..7 elements, same as the amount of fields per each record.

      What it will do is, loop through the hash and if the current hash element's length is greater than the value in the same position in @colLens, then that element in @colLens will now big the bigger of the two. So the end effect will be that @colLens holds the largest length of each hash element 0..7 .

      Here's what I tried:
      my @header = ("RECORD_ID", "STATUS", "PID", "TIME", "DATE", "HELD/WAIT +ING", "FILENAME", "USER"); my @colLens; sub getColumnLengths() { for (my $y = 0; $y <= $#header; $y++) { $colLens[$y] = length($header[$y]); } my $x; # $rec1 = RECORD_ID for my $rec1 ( keys %records ) { $x = 0; if (int($colLens[$x]) < length($rec1)) { $colLens[$x] = length($rec1); } # $rec2 = STATUS for my $rec2 ( keys %{ $records{$rec1} } ) { $x = 1; if (int($colLens[$x]) < length($rec2)) { $colLens[$x] = length($rec2); } $x++; # $rec3 = PID, TIME, DATE, ELAPSED, FILENAME, USER for my $rec3 ( keys %{$records{$rec1}{$rec2}} ) { if (int($colLens[$x]) < int(length($rec3))) { $colLens[$x] = int(length($rec3)); } $x++; }#END INNER-MOST }#END MID }#END OUTER }

      From my output I get it seems that it is working for just the first 2 elements, not sure why the rest isn't? I'm assuming it is something with my inner-most loop...

      If you can think of anything please let me know.

      Thanks in Advance,

        I don't quite understand what you are doing here, but generally you ought to avoid nested loops. I suspect this for-for-for can be achieved earlier, when you are first building %records.

        But as you have it, confirm what is happening with temporary print statements before each of your assignments:

        if (int($colLens[$x]) < length($rec1)) { printf "colLens:%s, rec1:%s\n", $colLens[$x], $rec1; $colLens[$x] = length($rec1); ...

        Also, stylistically, instead of:

        for (my $y = 0; $y <= $#header; $y++) { $colLens[$y] = length($header[$y]); }


        @colLens = map length, @header;

        I look forward to your final, working program!

        Update: I also meant to say, you have int(length(...)) in a few places. length returns an integer, so no need to wrap it with int.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://927014]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (5)
As of 2018-06-19 03:10 GMT
Find Nodes?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?

    Results (111 votes). Check out past polls.