Мой модуль Список :: Gen содержит функцию cartesian
, которая может выдавать желаемые результаты.Этот код, кажется, делает свое дело, но ваш пример не содержит всех перестановок, которые это произведет, что я предполагаю, просто упущение в примере.
use List::Gen 'cartesian';
my %data = (
'a' => [qw(a1 a2 a3)],
'b' => [qw(b1 b2 b3)],
'c' => [qw(c1 c2 c3)],
);
my $product = cartesian {join ' ' => sort grep defined, @_}
map {[@$_, undef]}
values %data;
say for sort {length $a <=> length $b or $a cmp $b} @$product;
Это немного плотно,поясню:
values %data
возвращает массивы в %data
map {[@$_, undef]}
, затем присоединяет пустое значение к концу каждого, так как вам нужны частичные комбинации cartesian {join ' ' => sort grep defined, @_}
затем выполняет основную работу, вычисляя декартово произведение массивов, вычитая неопределенные элементы и сортируя значения, как показано в вашем примере. sort {length $a <=> length $b or $a cmp $b} @$product
, затем печатаеттовар в указанном порядке.