perl - все возможные комбинации хэша - PullRequest
1 голос
/ 29 декабря 2010

подскажите, как получить все возможные комбинации хешей

Вот пример

my %data = (
'a' => [qw(a1 a2 a3)],
'b' => [qw(b1 b2 b3)],
'c' => [qw(c1 c2 c3)]);

, чтобы получить

a1
a2
a3
b1
b2
b3
c1
c2
c3

a1 b1
a1 b2
a1 b3
a1 c1
a1 c2
a1 c3

b1 c1
b1 c2
b1 c3
b2 c1
b2 c2
b2 c3
b3 c1
b3 c2
b3 c3

a1 b1 c1
a1 b1 c2
a1 b1 c3
a1 b2 c1
a1 b2 c2
a1 b2 c3
a1 b3 c1
a1 b3 c2
a1 b3 c3
a2 b1 c1
a2 b1 c2
a2 b1 c3
a2 b2 c1
a2 b2 c2
a2 b2 c3
a2 b3 c1
a2 b3 c2
a2 b3 c3
a3 b1 c1
a3 b1 c2
a3 b1 c3
a3 b2 c1
a3 b2 c2
a3 b2 c3
a3 b3 c1
a3 b3 c2
a3 b3 c3

спасибо

Ответы [ 2 ]

6 голосов
/ 29 декабря 2010

Используйте модуль Брайана Д Фой Set::CrossProduct. Вам нужно будет втирать ваш хэш в массив массивов очевидным образом.

use Set::CrossProduct;
my $iterator = Set::CrossProduct->new( ARRAY_OF_ARRAYS );
my $tuples = $iterator->combinations;
5 голосов
/ 29 декабря 2010

Мой модуль Список :: 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, затем печатаеттовар в указанном порядке.
...