Home > Blockchain >  Iterating over Multi-Level Hashes
Iterating over Multi-Level Hashes

Time:10-14

I am reading a CSV file into a multi-level hash. I am trying to iterate over the hash.

This is the code that loads the hash. It works. If I use Dumper to print it, I have what I expect.

use Data::Dumper;


my $connectionsinfile = "switchconnections.csv";
my %switchportinfo;

open (my $INFILE,'<',$connectionsinfile) or die "Couldn't open SVC input file $connectionsinfile\n$!";
my @recs = <$INFILE>;
close $INFILE;
chomp @recs;

  use constant { true => 1, false => 0};
   my @header = split',', $recs[0];

# now that we have the header, remove it from the array
  shift @recs;
foreach my $rec (@recs) {
        
        my @data = split(',',$rec);
        @row_data{@header} = @data;
        my $switchname = $row_data{'Switch Name'};
    my $switchport = $row_data{'Port'};
        $switchportinfo{$switchname}{$switchport} = {%row_data};
}

This code works except it prints the outer and inner keys and then a value of 'HASH(XXXXXX)' for the inner key

for $key (keys %switchportinfo) 
{
    print "$key: \n";
    for $ele (keys %{$switchportinfo{$key}})
    {   
        
        print "  $ele: " . $switchportinfo{$key}->{$ele} . "\n";
    }
}

This code causes the error "type of arg 1 to keys must be hash or array (not key/value hash slice) at test2.pl "}

I want to be able to print the inner hash values.

for $key (keys %switchportinfo) 
{
    print "$key: \n";
    for $ele (keys %{$switchportinfo{$key}})
    {   
        print "$ele: \n";
        for $ele2 (keys %{switchportinfo{$key}{$ele}}) {
         print "   $ele2:  " . $switchportinfo{$key}{$ele}->{$ele2}. "\n";
        }
       
    }
}

CodePudding user response:

You're missing a $ in %{switchportinfo{$key}{$ele}}. ALWAYS use use strict; use warnings;.

The last snippet is otherwise correct. But let's use better names, such as the one used in the first snippet.

for my $switchname (keys %switchportinfo) 
{
   print "switchname: $switchname\n";
   for my $switchport (keys %{ $switchportinfo{$switchname} })
   {   
      print "   switchport: $switchport\n";
      for my $header (keys %{ $switchportinfo{$switchname}{$switchport} }) {
         print "     $header: $switchportinfo{$switchname}{$switchport}{$header}\n";
      }
   }
}

CodePudding user response:

Following sample code demonstrates one of possible scenario of processing input data and output collected records.

Note: no input file format was not provided, sample code based on an assumption of possible input format

use strict;
use warnings;
use feature 'say';

use Data::Dumper;

my $debug = 0;

my($header,@header,@recs,%sw_info);
$header = <DATA>;
@recs   = <DATA>;

@header = split(',',$header);

chomp @header;
chomp @recs;

foreach my $rec (@recs) {
        my %sw;
        @sw{@header} = split(',',$rec);
        $sw_info{$sw{name}}{$sw{port}} = \%sw;
}

say Dumper(\%sw_info) if $debug;

for my $sw ( sort keys %sw_info ) {
    say 'Switch: ' . $sw;
    say "=" x 45;
    for my $port ( keys %{$sw_info{$sw}} )
    {
        my $port_info = $sw_info{$sw}{$port};
        say "\t$_ => $port_info->{$_} " for sort keys %$port_info;
        say "\t" . '-' x 25;
    }
}

__DATA__
r #,name,port,ip,location
1,sw1,12,192.168.0.1,office 35/north side
2,sw4,8,192.168.1.15,office 31/west side
3,sw1,24,192.168.0.13,office 41/south side
4,sw1,15,192.168.0.11,office 23/south side

Output

Switch: sw1
=============================================
        ip => 192.168.0.11
        location => office 23/south side
        name => sw1
        port => 15
        r # => 4
        -------------------------
        ip => 192.168.0.13
        location => office 41/south side
        name => sw1
        port => 24
        r # => 3
        -------------------------
        ip => 192.168.0.1
        location => office 35/north side
        name => sw1
        port => 12
        r # => 1
        -------------------------
Switch: sw4
=============================================
        ip => 192.168.1.15
        location => office 31/west side
        name => sw4
        port => 8
        r # => 2
        -------------------------
  •  Tags:  
  • perl
  • Related