我在Perl中有一个列表,我正在尝试“扩展”它包含的任何列表。
例如:
my @l = (
'foo',
['A', 'B'],
'bar',
['X', 'Y', 'Z'],
'baz',
);
我想扩展列表以获取此信息:
my @want = (
[qw/ foo A bar X baz /],
[qw/ foo A bar Y baz /],
[qw/ foo A bar Z baz /],
[qw/ foo B bar X baz /],
[qw/ foo B bar Y baz /],
[qw/ foo B bar Z baz /],
);
我想出了这个,它有效,但很难看,并且没有产生明智的有序阵列:
my @out = ([]);
foreach my $elt (@l){
if( ref($elt) eq 'ARRAY' ){
my $n = scalar(@$elt);
my @_out;
# expand
for( my $i=0; $i<$n; $i++ ){
foreach my $o (@out){
push(@_out, [@$o]);
}
}
for( my $i=0; $i<@_out; $i++ ){
push(@{$_out[$i]}, $elt->[$i % $n]);
}
@out = @_out;
}
else{
foreach my $o (@out){
push(@$o, $elt);
}
}
}
是否有更简洁的方法来完成此操作?
答案 0 :(得分:2)
看起来您正在尝试计算阵列中元素的笛卡尔积。您可以使用CPAN中的Math::Cartesian::Product
执行此操作:
use strict;
use warnings;
use Math::Cartesian::Product;
cartesian { print "@_","\n"; }
([qw(foo)], [qw(A B)], [qw(bar)], [qw(X Y Z)], [qw(baz)]);
# outputs
# foo A bar X baz
# foo A bar Y baz
# foo A bar Z baz
# foo B bar X baz
# foo B bar Y baz
# foo B bar Z baz
注意,这确实需要您将每个输入元素放在arrayref中,如果您想要一个arrayrefs数组作为输出(从您的示例中),您将需要在块中编码该逻辑。
答案 1 :(得分:0)
虽然这是一个旧线程,但我想我会添加另一个可能的解决方案
模块Set::CrossProduct也会得到想要的结果。 (输入数组元素必须都是数组引用。)
SELECT * FROM Users WHERE login="john";
SELECT * FROM Users WHERE login="John";
SELECT * FROM Users WHERE login="JOHN";
SELECT * FROM Users WHERE login="jOHn";
数据转储输出
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dump;
use Set::CrossProduct;
my @l = (
'foo',
['A', 'B'],
'bar',
['X', 'Y', 'Z'],
'baz',
);
# all elements of array must be array refs
@l = map ref eq 'ARRAY' ? $_ : [$_], @l;
my @wanted = Set::CrossProduct->new(\@l)->combinations;
dd \@wanted;