Glob用于生成所有排列

时间:2014-02-26 22:34:12

标签: perl combinations glob

我使用以下代码生成排列的所有可能组合并将其存储在@apirirow中,这适用于小$ globstring,但对于大输入会产生null @apirirow。我该如何解决这个问题?

$globstring = join ',', @distinctelements;
@apriorirow = glob "{$globstring}" x $i;

print "$globstring";

1 个答案:

答案 0 :(得分:3)

使用glob生成的内容既不是组合也不是排列,而是Cartesian product(也称为交叉产品)。将笛卡尔积存储在数组中将为大量输入数据使用大量内存。您可以使用Set::CrossProduct一次迭代笛卡尔积一个元组:

use Set::CrossProduct;

my $rows = 3;
my @elements = qw(a b c);

my @array;
push @array, \@elements for 1..$rows;

my $iterator = Set::CrossProduct->new(\@array);
while (my $tuple = $iterator->get) {
    say join ',', @$tuple;
}

输出:

a,a,a
a,a,b
a,a,c
a,b,a
a,b,b
a,b,c
a,c,a
a,c,b
a,c,c
b,a,a
b,a,b
b,a,c
b,b,a
b,b,b
b,b,c
b,c,a
b,c,b
b,c,c
c,a,a
c,a,b
c,a,c
c,b,a
c,b,b
c,b,c
c,c,a
c,c,b
c,c,c

当然,您也可以使用glob进行迭代:

perl -wE 'say while glob "{a,b,c}" x 3'

基本上会做同样的事情。但我发现Set :: CrossProduct的意图更清晰,而更喜欢使用数组而不是逗号分隔的字符串(更不用说附加功能了Set :: CrossProduct就像在下一个元组中偷看而没有实际迭代)。