Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Hash of arrays of hashes

by bArriaM (Initiate)
on Apr 14, 2013 at 17:32 UTC ( #1028634=perlquestion: print w/ replies, xml ) Need Help??
bArriaM has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I'm trying to update a device's configuration by using a strange hash of arrays of hashes. It's not really beautiful but it's the best way I found out so far. The HASH looks like this:

my %INPUT_DATA = ( 'DEVICE1_NAME' => [ '1/1/5/40' => { 'ACTUAL' => { 'SVC' => '239', 'SPTM' => '112', }, 'NEW' => { 'SVC' => '239', 'SPTM' => '183', }, }, ], 'DEVICE2_NAME' => [ '1/1/5/30' => { 'ACTUAL' => { 'SVC' => '239', 'SPTM' => '112', }, 'NEW' => { 'SVC' => '239', 'SPTM' => '183', }, }, '1/1/7/1' => { 'ACTUAL' => { 'SVC' => '124', 'SPTM' => '112', }, 'NEW' => { 'SVC' => '124', 'SPTM' => '183', }, }, '1/1/7/23' => { 'ACTUAL' => { 'SVC' => '194', 'SPTM' => '112', }, 'NEW' => { 'SVC' => '194', 'SPTM' => '183', }, }, ], );

Now, when I try some commands, the result looks like this (half good):

leg:isadmin># show xdsl operational-data line 1/1/5/30 detail leg:isadmin># show xdsl operational-data line HASH(0x53e228) detail leg:isadmin># show xdsl operational-data line 1/1/7/1 detail leg:isadmin># show xdsl operational-data line HASH(0x53e2e8) detail leg:isadmin># show xdsl operational-data line 1/1/7/23 detail leg:isadmin># show xdsl operational-data line HASH(0x53e3a8) detail

You see, the first command is good, then I have a reference to a hash, then a good command, etc.

Here's the output from Dumper:

$VAR1 = 'DEVICE1_NAME'; $VAR2 = [ '1/1/5/40', { 'NEW' => { 'SVC' => '239', 'SPTM' => '183' }, 'ACTUAL' => { 'SVC' => '239', 'SPTM' => '112' } } ]; $VAR3 = 'DEVICE2_NAME'; $VAR4 = [ '1/1/5/30', { 'NEW' => { 'SVC' => '239', 'SPTM' => '183' }, 'ACTUAL' => { 'SVC' => '239', 'SPTM' => '112' } }, '1/1/7/1', { 'NEW' => { 'SVC' => '124', 'SPTM' => '183' }, 'ACTUAL' => { 'SVC' => '124', 'SPTM' => '112' } }, '1/1/7/23', { 'NEW' => { 'SVC' => '194', 'SPTM' => '183' }, 'ACTUAL' => { 'SVC' => '194', 'SPTM' => '112' } } ];

Hope someone can help! Thanks!

EDIT: here's the loop I use to go through the whole hash and print a command:

foreach my $current_port ( @{$INPUT_DATA{$device_name}} ) { my @CURRENT_PORT_STATUS = $session->cmd( "show xdsl operational\-d +ata line $current_port detail" ); }

Comment on Hash of arrays of hashes
Select or Download Code
Re: Hash of arrays of hashes
by NetWallah (Abbot) on Apr 14, 2013 at 18:40 UTC
    Change your data structure to be closer to how your data actually looks.
    I.E. instead of squeezing a hashref into an array, make it a real hashref:
    Replace "[]" with "{}" in your data;
    You can always "SORT" it later, if necessary.
    my %INPUT_DATA = ( 'DEVICE1_NAME' => { '1/1/5/40' => { 'ACTUAL' => { 'SVC' => '239', 'SPTM' => '112', }, 'NEW' => { 'SVC' => '239', 'SPTM' => '183', }, }, }, ... # Now, you can use: #....set $device_name #.... foreach my $current_port ( sort keys %{$INPUT_DATA{$device_name}} ) { my @CURRENT_PORT_STATUS = print( "show xdsl operational\-data line + $current_port detail"); }
    A simple sort is used above. In real life, your sort sub may be complicated if you want to preserve true numeric order in the port.
    One alternative is to add an ORDER field within the port info, and manually increment it. That field can subsequently be used as a sort key. There are also modules that provide (tied) ordered-key hashes. (eg: Data::XHash).

    Update: If you really wanted to keep the current data structure (in case it came from outside your control), you will need to process every other element : i.e. skip the hashref, process only the "key" which is a scalar.
    To do this, the first thing in the "for loop" should be:

    next unless ref $current_port eq ""; # skip if $current port is NO +T a scalar.

                 "I'm fairly sure if they took porn off the Internet, there'd only be one website left, and it'd be called 'Bring Back the Porn!'"
            -- Dr. Cox, Scrubs

      next unless ref $current_port eq ""; # skip if $current port is NOT a +scalar.

      Wouldn't this be better if more directly stated as
          next if ref $current_port;  # skip if $current port IS a reference
      thus avoiding the double negative?

        Agreed that your code is shorter/better. Disagree that mine has a double-negative.

                     "I'm fairly sure if they took porn off the Internet, there'd only be one website left, and it'd be called 'Bring Back the Porn!'"
                -- Dr. Cox, Scrubs

      Thanks NetWallah, my logic was good but my idea wasn't. I thought that I needed that ARRAY of ports but when I saw your example I understood that it wasn't required at all. Much more efficient the way you showed me! In fact I was able to "fix" my problem by creating 2 independent HASH. But I tried your way and it does the right job. Thanks again, I appreciate it!

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1028634]
Approved by aitap
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (14)
As of 2014-08-27 16:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (244 votes), past polls