2012-04-24 107 views
16

我有一个带有列表的文件,需要制作一个文件来比较每一行。例如,我的文件中有这样的:在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,对于这个第一次和我有有点麻烦。我知道你需要创建一个数组,然后将其拆分,但之后我遇到了一些麻烦。

+0

请发表您的到目前为止的代码。 – tuxuday 2012-04-24 14:26:46

回答

0
  1. 采取第一串
  2. 迭代过阵列从下一个位置以结束
    1. 下一个字符串附加到原始字符串
  3. 采取下一个字符串并返回到步骤2
7

看看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 
+3

为什么不使用问题中的示例数据? – daxim 2012-04-24 14:54:12

+1

@daxim:内涵是为OP留下一些工作。 – 2012-04-25 05:48:43

0

如何:

#!/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", 
) 
+5

全局技巧应该总是伴随着各种失败告诫。 – daxim 2012-04-24 14:51:47

+1

@daxim:你的意思是在当前工作目录中匹配文件的“副作用”?如果是这样,这是不是很安全,因为他不使用'?','[]'或'*'? – flesk 2012-04-25 06:22:40

+1

所有这一切。我现在很恼火,这些警告应该作为答案的一部分清楚地列出,而不是作为低能见度评论附带的修辞问题。这不是一个“副作用”,它确实发生,模糊这个词是错误的。这是不安全的:显然用户在问题中提供了伪造/匿名数据,并且在真实世界条件下会出现一个糟糕的惊喜。 SO答案应该努力不让人们失败,他们应该总是意识到微妙和风险;鉴于此,我现在已经低估了这个答案,为M42提供了改进它的动机。 - 续: – daxim 2012-04-25 07:40:38

28

使用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
0

下面是使用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::ExpandString::Glob::Permute模块而不是简单的​​3210来避免当前工作目录中匹配文件的警告。

+4

全局技巧应该总是伴随着各种失败告诫。 – daxim 2012-04-24 15:15:19

8

使用递归编写这个很简单。

此代码示例演示。

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 
相关问题