Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Recurse over a hash without knowing any elements (except top level)

Reply
Thread Tools

Recurse over a hash without knowing any elements (except top level)

 
 
Christopher
Guest
Posts: n/a
 
      02-12-2004
I have a hash that is several levels deep.

ie:

'vars' => {
'$filers' => '10.10.10.10/32',
'$networksa' => '10.10.10.10/32',
'$networksb' => '10.50.0.0/16',
'$wintel_boxes' => '10.10.10.10/32',
},
'match' => {
'Rule' => {
'Doug' => {
'RuleSub' => {
'OUTBREAK' => {


Basically a structure similar in nature to that, basically it could go
as deep as 8 keys deep with values potentially with each key, but
usually a value as some level.

I need to iterate over this and print it out in it's structure, but
with some formatting. DataDumper does a fine job of doing it in it's
way, but I cannot customize the pretty output, plus I need to utilize
the data in other ways.

So I figure I can load the "top level" keys (say there are 3 of them),
and then recurse over each subsequent key and gather and print as I
go.

Here is what I tried:

use Config::General;

my $match_file = qq(match.conf);

my $match_conf = new Config::General(
-file => $match_file,
-AutoTrue => 1);

my %match_config = $match_conf->getall;

$depth = 0;

foreach $key (keys %match_config) {
print "\t"x$depth;
print "\n$key\n";
$depth++;
&recurse_hash($match_config{$key},$depth);
}

sub recurse_hash {

$match = shift;
$depth = shift;

print "\t"x$depth;

foreach $key2 (keys %{$match}) {
print "$key2 => $match->{$key2}\n";
($match,$depth) = &recurse_hash($match->{$key2},$depth);
}
return ($match,$depth);
}

I get some results back, but I also get some funk, plus I don't get it
all, just portions..... I have racked my brain on this, and scoured
the groups for anykind of similar problem. Most are only 3 levels
deep, and the levels are known.

Here is the results:
Top level keys are typically gonna be (vars, match, and translate):
vars
$filers =>
$networksa =>
$networksb =>
$wintel_boxes =>

match
Rule => HASH(0x17a91
DOUG => HASH(0x17a924)
RuleSub => HASH(0x17a99c)
OUTBREAK => HASH(0x17a9a
mail_body => blah blahblah
mail_cc =>
page_cc =>
interval =>
GUN =>
DOS =>
PN =>
srcnet =>

translate
CT2 => HASH(0x183a44)
27-74 => HASH(0x183abc)
msg_pattern => HASH(0x183b04)
".*filename: => (.*)" = "Bad file: \1"
27-75 =>
SN =>
MSG =>
 
Reply With Quote
 
 
 
 
nobull@mail.com
Guest
Posts: n/a
 
      02-13-2004
http://www.velocityreviews.com/forums/(E-Mail Removed) (Christopher) wrote in message news:<(E-Mail Removed). com>...
> I have a hash that is several levels deep.
>
> ie:
>
> 'vars' => {
> '$filers' => '10.10.10.10/32',
> '$networksa' => '10.10.10.10/32',
> '$networksb' => '10.50.0.0/16',
> '$wintel_boxes' => '10.10.10.10/32',
> },
> 'match' => {
> 'Rule' => {
> 'Doug' => {
> 'RuleSub' => {
> 'OUTBREAK' => {
>
>
> Basically a structure similar in nature to that, basically it could go
> as deep as 8 keys deep with values potentially with each key, but
> usually a value as some level.
>
> I need to iterate over this and print it out in it's structure, but
> with some formatting. DataDumper does a fine job of doing it in it's
> way, but I cannot customize the pretty output, plus I need to utilize
> the data in other ways.
>
> So I figure I can load the "top level" keys (say there are 3 of them),
> and then recurse over each subsequent key and gather and print as I
> go.
>
> Here is what I tried:
>
> use Config::General;
>
> my $match_file = qq(match.conf);
>
> my $match_conf = new Config::General(
> -file => $match_file,
> -AutoTrue => 1);
>
> my %match_config = $match_conf->getall;
>
> $depth = 0;


You forgot to declare $depth. "use strict" would have told you about
this.

> foreach $key (keys %match_config) {
> print "\t"x$depth;


You forgot to declare $key. "use strict" would have told you about
this.

> print "\n$key\n";
> $depth++;
> &recurse_hash($match_config{$key},$depth);


Why is that & in there? Do you know what it does? Do you really want
to do that?

Assuming $depth is supposed to indicate the depth within the
structure, it would be more straight-forward to do

recurse_hash($match_config{$key},1);

Anyhow it's not clear why you treat the top level specially at all.

recurse_hash(\%match_config,0);


> }
>
> sub recurse_hash {
>
> $match = shift;


You forgot to declare $match. "use strict" would have told you about
this. By choosing not to "use strict" you instruct Perl to assume any
variable you didn't declare is a package variable and thus a global
variable with respect to the subroutine. Using global variables in
recursive subroutines is bad.

> $depth = shift;


Ouch - you forgot to redeclare $depth within the subroutine. "use
strict" would not have helped you directly. But the mind-set that
goes with "use strict" that says "always declare all variables
lexically scoped in the smallest lexical scope" would have made this
error much less likely.

> print "\t"x$depth;


You probably wanted that on each line - i.e inside the loop.

> foreach $key2 (keys %{$match}) {


You forgot to declare $key2. "use strict" would have told you about
this.

> print "$key2 => $match->{$key2}\n";
> ($match,$depth) = &recurse_hash($match->{$key2},$depth);


You are forgetting to check that $match->{$key2} really is a hash ref
either before you call &recurse_hash or within that inner subroutine.
"use strict" would have told you about this because you'd have got an
error when you tried to use something that wasn't a hash ref as a has
ref. Without "use strict" Perl will attempt to convert the string
into a reference by performing a symbol table lookup - this is bad.

Once again assuming $depth is supposed to indicate the depth within
the structure, you should be calling recurse_hash with $depth+1.

> }
> return ($match,$depth);
> }


I do not understand why &recurse_hash needs to return this.

sub recurse_hash {

my $match = shift;
my $depth = shift;

return unless ref $match eq 'HASH';

foreach my $key2 (keys %{$match}) {
print "\t"x$depth, "$key2 => $match->{$key2}\n";
recurse_hash($match->{$key2},$depth+1);
}
}

> I have racked my brain on this, and scoured
> the groups for anykind of similar problem.


The consequences of being careles about your variable scoping and
choosing not to "use strict" are often discussed (oftem many times per
day) in the Perl newsgroups that exist. But, of course, you could not
be expected to realise that those are all "similar problems".

I would have thought recursive traversal of Perl structures is
dicussed frequently in the Perl newsgroups that exist. Usually at
least once a month. But actually, having Googled "recursive reference
group:comp.lang.perl.*" it does seem much less common than I'd expect.

Indeed the last thread I could find asking substancially the same
question as you are asking was the sixth hit I got and was way back in
August/September.

That said trawling though six hits isn't all that ownerous. When you
"scoured
the groups for anykind of similar problem" what keywords did you try?

This newsgroup does not (see FAQ). Please do not start threads here.
 
Reply With Quote
 
 
 
 
Christopher
Guest
Posts: n/a
 
      02-16-2004
I appreciate your time to go through my code. I admit that I have been
quite careless, and that I am trying to rectify that habit.

I search on "recurse hash", and probably did not use have the best use
of keywords.

Anway, again thank you for your insight.

-Chris


(E-Mail Removed) wrote in message news:<(E-Mail Removed). com>...
> (E-Mail Removed) (Christopher) wrote in message news:<(E-Mail Removed). com>...

<snipped>
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
hash of hash of hash of hash in c++ rp C++ 1 11-10-2011 04:45 PM
VOIP over VPN over TCP over WAP over 3G Theo Markettos UK VOIP 2 02-14-2008 03:27 PM
newb: recurse over elements children and disable all form elements SteveKlett@gmail.com Javascript 4 09-20-2006 07:42 AM
Recurse Directories and process files in directory KraftDiner Python 5 08-13-2006 12:47 AM
rcase-Recurse with xs:redefine nested groups Cat XML 1 01-27-2005 04:42 AM



Advertisments