我有一个带有列表的文件,需要制作一个文件来比较每一行。例如,我的文件中有这样的:在Perl中,如何生成列表的所有可能组合?
AAA BBB CCC DDD EEE
我想最终名单看起来像这样:
AAA BBB AAA CCC AAA DDD AAA EEE BBB CCC BBB DDD BBB EEE CCC DDD CCC EEE DDD EEE
我试图做到这一点在Perl,对于这个第一次和我有有点麻烦。我知道你需要创建一个数组,然后将其拆分,但之后我遇到了一些麻烦。
我有一个带有列表的文件,需要制作一个文件来比较每一行。例如,我的文件中有这样的:在Perl中,如何生成列表的所有可能组合?
AAA BBB CCC DDD EEE
我想最终名单看起来像这样:
AAA BBB AAA CCC AAA DDD AAA EEE BBB CCC BBB DDD BBB EEE CCC DDD CCC EEE DDD EEE
我试图做到这一点在Perl,对于这个第一次和我有有点麻烦。我知道你需要创建一个数组,然后将其拆分,但之后我遇到了一些麻烦。
看看Math::Combinatorics - 在列表上执行组合和排列
例如从CPAN复制:
use Math::Combinatorics;
my @n = qw(a b c);
my $combinat = Math::Combinatorics->new(count => 2,
data => [@n],
);
print "combinations of 2 from: ".join(" ",@n)."\n";
print "------------------------".("--" x scalar(@n))."\n";
while(my @combo = $combinat->next_combination){
print join(' ', @combo)."\n";
}
print "\n";
print "permutations of 3 from: ".join(" ",@n)."\n";
print "------------------------".("--" x scalar(@n))."\n";
while(my @permu = $combinat->next_permutation){
print join(' ', @permu)."\n";
}
output:
combinations of 2 from: a b c
------------------------------
a b
a c
b c
permutations of 3 from: a b c
------------------------------
a b c
a c b
b a c
b c a
c a b
c b a
为什么不使用问题中的示例数据? – daxim 2012-04-24 14:54:12
@daxim:内涵是为OP留下一些工作。 – 2012-04-25 05:48:43
如何:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dump qw(dump);
my @in = qw(AAA BBB CCC DDD EEE);
my @list;
while(my $first = shift @in) {
last unless @in;
my $rest = join',',@in;
push @list, glob("{$first}{$rest}");
}
dump @list;
输出:
(
"AAABBB",
"AAACCC",
"AAADDD",
"AAAEEE",
"BBBCCC",
"BBBDDD",
"BBBEEE",
"CCCDDD",
"CCCEEE",
"DDDEEE",
)
全局技巧应该总是伴随着各种失败告诫。 – daxim 2012-04-24 14:51:47
@daxim:你的意思是在当前工作目录中匹配文件的“副作用”?如果是这样,这是不是很安全,因为他不使用'?','[]'或'*'? – flesk 2012-04-25 06:22:40
所有这一切。我现在很恼火,这些警告应该作为答案的一部分清楚地列出,而不是作为低能见度评论附带的修辞问题。这不是一个“副作用”,它确实发生,模糊这个词是错误的。这是不安全的:显然用户在问题中提供了伪造/匿名数据,并且在真实世界条件下会出现一个糟糕的惊喜。 SO答案应该努力不让人们失败,他们应该总是意识到微妙和风险;鉴于此,我现在已经低估了这个答案,为M42提供了改进它的动机。 - 续: – daxim 2012-04-25 07:40:38
使用Algorithm::Combinatorics。基于迭代器的方法优于一次生成所有内容。
#!/usr/bin/env perl
use strict; use warnings;
use Algorithm::Combinatorics qw(combinations);
my $strings = [qw(AAA BBB CCC DDD EEE)];
my $iter = combinations($strings, 2);
while (my $c = $iter->next) {
print "@$c\n";
}
输出:
AAA BBB AAA CCC AAA DDD AAA EEE BBB CCC BBB DDD BBB EEE CCC DDD CCC EEE DDD EEE
下面是使用glob
一个黑客:
my @list = qw(AAA BBB CCC DDD EEE);
for my $i (0..$#list-1) {
print join "\n", glob sprintf "{'$list[$i] '}{%s}",
join ",", @list[$i+1..$#list];
print "\n";
}
输出:
AAA BBB
AAA CCC
AAA DDD
AAA EEE
BBB CCC
BBB DDD
BBB EEE
CCC DDD
CCC EEE
DDD EEE
附:您可能希望使用Text::Glob::Expand
或String::Glob::Permute
模块而不是简单的3210来避免当前工作目录中匹配文件的警告。
全局技巧应该总是伴随着各种失败告诫。 – daxim 2012-04-24 15:15:19
使用递归编写这个很简单。
此代码示例演示。
use strict;
use warnings;
my $strings = [qw(AAA BBB CCC DDD EEE)];
sub combine;
print "@$_\n" for combine $strings, 5;
sub combine {
my ($list, $n) = @_;
die "Insufficient list members" if $n > @$list;
return map [$_], @$list if $n <= 1;
my @comb;
for my $i (0 .. $#$list) {
my @rest = @$list;
my $val = splice @rest, $i, 1;
push @comb, [$val, @$_] for combine \@rest, $n-1;
}
return @comb;
}
编辑
我道歉 - 我正在生成的,而不是组合排列。
此代码是正确的。
use strict;
use warnings;
my $strings = [qw(AAA BBB CCC DDD EEE)];
sub combine;
print "@$_\n" for combine $strings, 2;
sub combine {
my ($list, $n) = @_;
die "Insufficient list members" if $n > @$list;
return map [$_], @$list if $n <= 1;
my @comb;
for (my $i = 0; $i+$n <= @$list; ++$i) {
my $val = $list->[$i];
my @rest = @$list[$i+1..$#$list];
push @comb, [$val, @$_] for combine \@rest, $n-1;
}
return @comb;
}
输出
AAA BBB
AAA CCC
AAA DDD
AAA EEE
BBB CCC
BBB DDD
BBB EEE
CCC DDD
CCC EEE
DDD EEE
请发表您的到目前为止的代码。 – tuxuday 2012-04-24 14:26:46