There is an example in the pod for Data::Rmap that shows how to use it's rmap_to() function to traverse a structure maintaining local state (the path through the hashes). It could be used as a starting point to create a custom iterator function.
# Traverse a tree using localize state
$tree = [
one =>
two =>
[
three_one =>
three_two =>
[
three_three_one =>
],
three_four =>
],
four =>
[
[
five_one_one =>
],
],
];
@path = ('q');
rmap_to {
if(ref $_) {
local(@path) = (@path, 1); # ARRAY adds a new level to the pa
+th
$_[0]->recurse(); # does stuff within local(@path)'s scope
} else {
print join('.', @path), " = $_ \n"; # show the scalar's path
}
$path[-1]++; # bump last element (even when it was an aref)
} ARRAY|VALUE, $tree;
# OUTPUT
# q.1 = one
# q.2 = two
# q.3.1 = three_one
# q.3.2 = three_two
# q.3.3.1 = three_three_one
# q.3.4 = three_four
# q.4 = four
# q.5.1.1 = five_one_one
This would involve writing your own function that wrapped code something similar to the above, but localise the keys on the fly. You would pass a callback (function or block) to the wrapper function, and it would call your code, with the appropriate variables ($env, $platform, $host, $target etc.) set and localised. You write this once the call with different callbacks each time you need to iterate the structure. If this idea interests you, but you need a bit more info on implementing it /msg me.
The other thought that crossed my mind was if you only ever access this structure through iteration, rather than individual direct accesses, then a HoH is probably the wrong structure. An AoH would be easier to use in that case. It might look something like this (pseudo-code):
my @servers = (
{
type => production | development,
env => Windows | unix | Database,
hostname => the hostname
targets => [
name1 => [ #total, #free ].
name2 => [ #total, #free ],
...
],
},
{
type => production | development,
env => Windows | unix | Database,
hostname => the hostname
targets => [
name1 => [ #total, #free ].
name2 => [ #total, #free ],
...
],
},
...
);
And to iterate it:
use constant { TOTAL => 0, FREE => 1 };
for my @server ( @servers ) {
printf "Server: %s type:%s Env: %s\n",
$server->{ hostname },
$server->{ type },
$server->{ env };
for my $target ( @{ $server->{ targets } } ) {
printf "\tTotal: %d Free: %d\n", @{ $target }[ TOTAL, FREE ];
}
}
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.