I have to make sense of this script , without making major changes and insulting the guy who made it. I can't change the hashes, even though it would be easy to load data into arrays and then split. The guy who wrote this (my boss) loves his multilevel hashes. I have to print out the %extend_hash multilevel hash - and I don't understand how to get to the last level. I need to print this out in to a CSV file that cane be read by salespeople. It looks like it goes out like 6 levels. I have to sort keys of a hash, of a hash, of a hash ...etc.
#!/scripts/perl/bin/perl
use strict;
use warnings;
use DBI;
my $dbUser = 'foo_01';
my $dbPass = 'foo_01';
my $dbSid = 'foo.WORLD';
my $dbh = DBI->connect("dbi:Oracle:$dbSid","$dbUser","$dbPass") or die( "Couldn't connect: $!" );
#sub read_extend
my %extend_hash = ();
my $query = "select level_id,e_risk_symbol,e_exch_dest,penny,specialist from etds_extend";
if(!$dbh) {
print "Error connecting to DataBase; $DBI::errstr\n";
}
my $cur_msg = $dbh->prepare($query) or die "\n\nCould not prepare statement: ".$dbh->errstr;
$cur_msg->execute();
while (my @row=$cur_msg->fetchrow_array) {
$extend_hash{$row[0]}{$row[1]}{$row[2]}{'penny'}=$row[3];
$extend_hash{$row[0]}{$row[1]}{$row[2]}{'specialist'}=$row[4];
}
for my $what_row0 (sort keys %extend_hash) {
for my $what_row1 (sort keys %{$extend_hash {$what_row0} }) {
for my $what_row2 (sort keys ..... I am lost.
I don't know how to print out the %extend_hash down to the lowest level I am trying to make it comma delimited, able to be pumped into an email and read by salespeople.
6,ACI,ARCX,specialist,1
6,ACI,ARCX,penny,0
6,MCHP,ARCX,specialist,1,
6,MCHP,ARCX,penny,0
6,BC,AMXO,specialist,1
6,BC,AMXO,penny,0
6,WM,XISX,specialist,1
6,WM,XISX,penny,0
6,PK,AMXO,specialist,1
6,PK,AMXO,penny,0
6,SPLS,XISX,specialist,1
6,SPLS,XISX,penny,0
If I use Data::Dumper I get this which is great, but the sales/marketing guys will get confused. They will not be able to see ARCX penny0 in realtions to the group '6'. I don't think they are able to mentally walt through the data::dump
$VAR1 = {
'6' => {
'IACI' => {
'ARCX' => {
'specialist' => '1',
'penny' => '0'
}
},
'MCHP' => {
'ARCX' => {
'specialist' => '1',
'penny' => '0'
}
},
'BC' => {
'AMXO' => {
'specialist' => '1',
'penny' => '0'
}
},
'WM' => {
'XISX' => {
'specialist' => '1',
'penny' => '0'
}
},
'PKD' => {
'AMXO' => {
'specialist' => '1',
'penny' => '0'
}
},
'SPLS' => {
'XISX' => {
'specialist' => '1',
'penny' => '0'
}
}
}
};
update - amazing work I_alarmed_alien - this should be a good stackoverflow reference (my comments are disabled)
for my $level_1 (sort keys %extend_hash) {
for my $level_2 (sort keys %{$extend_hash{$level_1} }) {
for my $level_3 (sort keys %{$extend_hash{$level_1}{$level_2}}) {
for my $type (sort keys %{$extend_hash{$level_1}{$level_2}{$level_3}} ) {
print "$level_1, $level_2, $level_3 $type" . " $extend_hash{$level_1}{$level_2}{$level_3}{$type}" ."\n" ;
}
}
}
}
got it - I_alarmed_alien amazing work outputing a hash of a hash of a hash of a hash of a hash of a hash
6, XLNX, AMXO , specialist 1
6, XLP, AMXO , penny 0
6, XLP, AMXO , specialist 1
6, XLP, XISX , penny 0
6, XLP, XISX , specialist 1
6, XLV, AMXO , penny 0
6, XLV, AMXO , specialist 1
6, XLY, AMXO , penny 0
6, XLY, AMXO , specialist 1
6, YUM, AMXO , penny 0
6, YUM, AMXO , specialist 1
6, ZINC, XISX , penny 0
6, ZINC, XISX , specialist 1
6, ZMH, AMXO , penny 0
6, ZMH, AMXO , specialist 1
You're almost there with your code. Here is how to get to the bottom of the hash:
foreach my $l1 (keys %extend_hash) {
# '6'
foreach my $l2 (keys %{$extend_hash{$l1}}) {
# IACI, MCHP, BC, etc.
foreach my $l3 (keys %{$extend_hash{$l1}{$l2}}) {
# ARCX, AMXO, XISX, etc.
foreach my $k (keys %{$extend_hash{$l1}{$l2}{$l3}}) {
print "$l1, $l2, $l3, $k, " . $extend_hash{$l1}{$l2}{$l3}{$k} . "\n";
}
}
}
}
Note that the hash keys are not accessed in any particular order, so you may want to sort them -- e.g. foreach my $l1 (sort keys %extend_hash)
.
Hashes of hashes of hashes of hashes are fun! ;)
ETA: Here is a more generic function for recursing into arbitrarily deep hashes-of-hashes-of-hashes-of...
sub print_hash {
# href = reference to the hash we're examining (i.e. \%extend_hash)
# so_far = arrayref containing the hash keys we are accessing
my $href = shift;
my $so_far = shift;
foreach my $k (keys %$href) {
# put $k on to the array of keys
push @$so_far, $k;
# if $href->{$k} is a reference to another hash, call print_hash on that hash
if (ref($href->{$k}) eq 'HASH') {
print_hash($href->{$k}, $so_far);
} else {
# $href->{$k} is a scalar, so print out @$so_far (our list of hash keys)
# and the value in $href->{$k}
print join(", ", @$so_far, $href->{$k}) . "\n";
}
# we've finished looking at $href->{$k}, so remove $k from the array of keys
pop @$so_far;
}
}
print_hash($hash, []);