Generate Combinations of Hash Values

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 from all combinations e.g.

 --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 contain any number of elements in an array of values. The order of the output array does not matter, you just need to have 1 element for each combination, 3 * 2 * 2 = 12 in this case, but it can be any number.

I think some combination of splicing, card and foreach should work, but I am not good at it to find it.

+5
source share
2 answers

As already mentioned, you are looking for a 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 
+7
source

The Set::Product module will do it for you.

Here is 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}; 

Output

 --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 
+4
source

Source: https://habr.com/ru/post/1247171/


All Articles