Quoth jkstill <>:
> I am trying to do something with hashes that I have not before.
>
> While I am sure it can be done, I can't think of a good way to do it.
>
> Given the following hash:
>
> my %h = (
> 'first' => {
> f0 => 'f_zero',
> f1 => 'f_one',
> },
> 'second' => {
> s0 => 's_zero',
> s1 => 's_one',
> }
> );
>
> ... print all possible combinations
It's not clear what you mean here by 'combinations'. I'm assuming you
mean 'combinations of values', so the result would be [[f_zero, s_zero],
[f_zero, s_one], [f_one, s_zero], [f_one, s_one]].
> Easy enough using 2 nested loops.
> Four combinations would be printed.
So you do mean what I said... the first thing to realize is that your
data structure should be arrays, not hashes:
[ ['f_zero', 'f_one'], ['s_zero', 's_one'] ]
since you don't make use of the keys.
> Extend the hash to this:
>
<snip: 3 inner hashes>
>
> This now requires 3 nested loops to get all possible combinations.
>
> The problem is that the number of hashes nested in the %h hash
> will not be known until runtime, so hardcoded loops won't work too
> well.
>
> Any tips on how to go about this?
The first thing that come to (my) mind is recursion, but of course you
can do it with loops as well. You only need three nested loops to handle
any number of cases.
#!/usr/bin/perl -l
use warnings;
use strict;
my %h = (
first => {
f1 => 'f1',
f2 => 'f2',
},
second => {
s1 => 's1',
s2 => 's2',
},
third => {
t1 => 't1',
t2 => 't2',
},
fourth => {
41 => '41',
42 => '42',
43 => '43',
},
);
$, = ',';
print "recurse:";
sub find_combs;
print @$_ for find_combs values %h;
sub find_combs {
my $entry = shift;
my @values = sort values %$entry;
@_ or return map [$_], @values;
my @recurse = find_combs @_;
my @rv;
for my $v (@values) {
push @rv, map [$v, @$_], @recurse;
}
return @rv;
}
print "reduce:";
use List::Util qw/reduce/;
my @lol = map [sort values %$_], sort values %h;
my $first = shift @lol;
our ($a, $b); # silence warnings
print @$_ for @{
reduce { # one...
[
map { # two...
my $tmp = $_;
map [$tmp, @$_], @$a; # three loops
} @$b
]
} [map [$_], @$first], @lol # (this map doesn't count

)
};
__END__
Ben