如何从此数组生成排列?

时间:2016-08-01 10:45:30

标签: arrays perl

我有一个数组

my @arr1 = ("A1", "B1,B2", "C1,C2,C3", ..); 

如何通过附加元素来创建新数组,以便从@ arr1中获取一个子元素,如A1,B1和& C1创建一个新元素" A1B1C1"。子元素由","分隔。数组元素编号是动态的。

因此生成的数组应该看起来像

@out = qw/A1B1C1 A1B1C2 A1B1C3 A1B2C1 A1B2C2 A1B2C3/; 

2 个答案:

答案 0 :(得分:7)

您可以执行动态递归或联系CPAN模块,但在这种情况下我会使用glob

my @out = glob join '', map "{$_}", @arr1;

答案 1 :(得分:4)

出于某些不可理喻的原因,我厌恶使用glob来生成这样的交叉产品。我不喜欢在生产代码中使用say,也许是因为它感觉像是一个调试工具

我认为以这种方式使用glob并没有错,但除了Zaid's fine answer

之外,我认为我应该提供基于模块的解决方案

很容易假设Math::CombinatoricsAlgorithm::Combinatorics可以帮助我们。与Graph一起,其中一个模块是Perl程序员工具箱的一个组件,但它们只能处理一组值,它是多个集合的交叉产品,是必需的这里

我选择了Brian Foy Set::CrossProduct

我的基准测试表明,它比glob技巧快了约150倍,但这并不重要,除非计算在您尝试优化的应用程序的关键路径上

use strict;
use warnings 'all';
use feature 'say';

use Set::CrossProduct;

my @arr1 = ('A1', 'B1,B2', 'C1,C2,C3');

my $iterator = Set::CrossProduct->new( [ map [ split /,/ ], @arr1 ] );

while ( my $tuple = $iterator->get ) {
    say join '', @$tuple;
}

输出

A1B1C1
A1B1C2
A1B1C3
A1B2C1
A1B2C2
A1B2C3

要以与 Zaid 答案插件兼容的方式使用此模块,您可以编写

my @out = map { join '', @$_ } $iterator->combinations;