In perl if I have a hash
my %ranges = (
'--tic' => [ 0, 1, 2 ],
'--threads' => [ 8, 16 ],
'--level' => [ 10, 20 ]
);
how can I generate an array of all the combinations, like
--level 10 --threads 8 --tic 0
--level 10 --threads 8 --tic 1
--level 10 --threads 8 --tic 2
--level 10 --threads 16 --tic 0
--level 10 --threads 16 --tic 1
--level 10 --threads 16 --tic 2
--level 20 --threads 8 --tic 0
--level 20 --threads 8 --tic 1
--level 20 --threads 8 --tic 2
--level 20 --threads 16 --tic 0
--level 20 --threads 16 --tic 1
--level 20 --threads 16 --tic 2
There can be any number of hash entries, and each entry can have any number of elements in it's value array. The order of the output array doesn't matter, just needs to have 1 element for each combination, 3*2*2 = 12 in this case, but could be any number.
I think some combination of splice, map, and foreach should work but I am flailing about in a bad way to find it.
As already mentioned, you're looking for Cartesian product,
use strict;
use warnings;
sub getCartesian {
#
my @input = @_;
my @ret = map [$_], @{ shift @input };
for my $a2 (@input) {
@ret = map {
my $v = $_;
map [@$v, $_], @$a2;
}
@ret;
}
return @ret;
}
my %ranges = (
'--tic' => [ 0, 1, 2 ],
'--threads' => [ 8, 16 ],
'--level' => [ 10, 20 ]
);
my @arr = map {
my $k = $_;
[ map "$k $_", @{$ranges{$k}} ];
}
keys %ranges;
print "@$_\n" for getCartesian(@arr);
output
--level 10 --tic 0 --threads 8
--level 10 --tic 0 --threads 16
--level 10 --tic 1 --threads 8
--level 10 --tic 1 --threads 16
--level 10 --tic 2 --threads 8
--level 10 --tic 2 --threads 16
--level 20 --tic 0 --threads 8
--level 20 --tic 0 --threads 16
--level 20 --tic 1 --threads 8
--level 20 --tic 1 --threads 16
--level 20 --tic 2 --threads 8
--level 20 --tic 2 --threads 16
The Set::Product
module will do this for you
Here's an example program
use strict;
use warnings 'all';
use Set::Product 'product';
my %ranges = (
'--tic' => [ 0, 1, 2 ],
'--threads' => [ 8, 16 ],
'--level' => [ 10, 20 ],
);
my @keys = sort keys %ranges;
product {
print join(' ', map { "$keys[$_] $_[$_]" } 0 .. $#keys), "\n";
} @ranges{@keys};
--level 10 --threads 8 --tic 0
--level 10 --threads 8 --tic 1
--level 10 --threads 8 --tic 2
--level 10 --threads 16 --tic 0
--level 10 --threads 16 --tic 1
--level 10 --threads 16 --tic 2
--level 20 --threads 8 --tic 0
--level 20 --threads 8 --tic 1
--level 20 --threads 8 --tic 2
--level 20 --threads 16 --tic 0
--level 20 --threads 16 --tic 1
--level 20 --threads 16 --tic 2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With