2010-12-28 2 views
2

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

Вот пример

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 

благодаря

+1

Вы сказали, что хотите получить любую возможную комбинацию, но даже при исключении перестановок мультиплетов, содержащих одни и те же члены, ваш пример не перечисляет все возможные комбинации - например, нет мультиплекса с участием a2. Каков ваш критерий для определения того, какую комбинацию вы хотите и какой из них вы не хотите? – canavanin

+0

Это не комбинация. Это перестановка, но только с подмножеством возможных расстройств. Объясните на словах принцип, согласно которому следует набор результатов, или, возможно, алгоритм. - edit: ↑ Да, что сказал канаванин. ↑ – daxim

ответ

4

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

Да это правильный выбор! Большое спасибо – DenverZ

+0

значения% данные возвращают значения в неопределенном порядке; Я подозреваю, что '@data {qw/a b c /}' будет лучше. – ysth

+0

@ysth => У меня был '@data {sort keys% data}' раньше, но я решил, что это лишний шаг, так как данные сортируются позже. –

4

Использование brian d foy's Set::CrossProduct модуль. Вы должны массировать свой хэш в массиве массивов очевидным образом.

use Set::CrossProduct; 
my $iterator = Set::CrossProduct->new(ARRAY_OF_ARRAYS); 
my $tuples = $iterator->combinations; 
+0

мне просто нужно, чтобы получить комбинацию a1 a2 a3 a1 b1 a1 b2 a1 b3 a1 c1 и т.д ... – DenverZ