【问题标题】:Print all possible combinations of an array of arrays打印数组数组的所有可能组合
【发布时间】:2016-09-02 04:55:30
【问题描述】:

我想获取三个文件,每个文件包含 80 行或更多行文本,并打印这三个文件的所有可能组合。

为了清楚起见,我们假设

文件 1 包含

1
2
3

文件2包含

4
5
6

文件3包含

7
8
9

如果我只想打印这些组合,那么我可以使用很多答案。但是,由于文件包含更多我关心的行,因此我需要在 Perl 脚本中手动键入。我正在从每个文件构建一个数组,然后我构建这些数组的数组引用。最后我尝试使用List::Permutor 打印组合。

我遇到的问题是我正在打印内存引用,但我无法弄清楚如何取消引用 List::Permutor 调用中的数组。

Perl 代码

use List::Permutor;
use warnings;

open (FILE, app_txt);
chomp (@app = (<FILE>));
close (FILE);

open (FILE, att1_txt);
chomp (@att1 = (<FILE>));
close (FILE);

open (FILE, att2_txt);
chomp (@att2 = (<FILE>));
close (FILE);

my $permutor = List::Permutor->new( \@app, \@att1, \@att2);

while ( my @permutation = $permutor->next() ) {
    print "@permutation\n";
}

【问题讨论】:

  • 请为您的 1,2,3 / 4,5,6 / 7,8,9 示例显示您想要的输出,只是为了说明您想要什么
  • “我正在尝试使用 List::Permutor 来打印组合” List::Permutor 用于生成排列。如果你想要 combinations 那么你需要一个不同的模块,也许是Math::Combinatorics
  • 您从 开始很好“为了清楚起见,我们假设 File1 包含...” 但您再也不会引用该数据,所以没有明确性!请根据简化数据解释您需要什么;那么我们将能够为您提供帮助

标签: arrays perl


【解决方案1】:

为此我写了Set::CrossProduct

【讨论】:

  • 哇,这确实是我想做的。那只留着下次用吧。谢谢!
【解决方案2】:

不清楚你想要什么。

请注意,以下 sn-ps 提供的所有输出均用于以下输入:

my @app  = ( 1, 2, 3 );
my @att1 = ( 4, 5, 6 );
my @att2 = ( 7, 8, 9 );

如果您想要数组的排列,您的代码将按原样运行。

use List::Permutor qw( );

my $permutor = List::Permutor->new( \@app, \@att1, \@att2);
while ( my @permutation = $permutor->next() ) {
   say join ", ", map { "[@$_]" } @permutation;
}

输出:

[1 2 3], [4 5 6], [7 8 9]
[1 2 3], [7 8 9], [4 5 6]
[4 5 6], [1 2 3], [7 8 9]
[4 5 6], [7 8 9], [1 2 3]
[7 8 9], [1 2 3], [4 5 6]
[7 8 9], [4 5 6], [1 2 3]

如果您想要数组内容的排列(无论字符串源自哪个数组),那么您只需要根据数组的内容创建一个列表。

use List::Permutor qw( );

my $permutor = List::Permutor->new( @app, @att1, @att2 );
while ( my @permutation = $permutor->next() ) {
   say "@permutation";
}

输出:

1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 9 8
1 2 3 4 5 6 8 7 9
1 2 3 4 5 6 8 9 7
1 2 3 4 5 6 9 7 8
1 2 3 4 5 6 9 8 7
1 2 3 4 5 7 6 8 9
1 2 3 4 5 7 6 9 8
1 2 3 4 5 7 8 6 9
1 2 3 4 5 7 8 9 6
...
9 8 7 6 5 4 3 2 1

请记住,P(80) 是可观测宇宙中原子数的 100,000,000,000,000,000,000,000,000,000,000,000,000 倍。


如果您想要每个数组中单个元素的所有可能集合,则可以使用以下方法:

for my $app (@app) {
for my $att1 (@att1) {
for my $att2 (@att2) {
   say "$app $att1 $att2";
}}}

use Algorithm::Loops qw( NestedLoops );

my $iter = NestedLoops([ \@app, \@att1, \@att2 ]);
while ( my ($app, $att1, $att2) = $iter->() ) {
   say "$app $att1 $att2";
}

输出:

1 4 7
1 4 8
1 4 9
1 5 7
1 5 8
1 5 9
1 6 7
1 6 8
1 6 9
2 4 7
...
3 6 9

【讨论】:

  • 不是有 492,960 种方式来排列 80 个项目吗?即80 * 79 * 78。如果他有3个文件,每个文件“大约80多个项目”,那么不是240个项目被排列吗?
  • @Marty,不,有 P(80,80) = 80! = 80*79*78*77*76*..*1 = 超过 7e118 种方式来排列 80 个项目。 /// 他没有说每个文件有80个项目。 /// 但是您提出了第三种解释,我已将其添加到我的答案中。 (尽管在这种解释下,当每个文件中有 80 个项目时,将有 P(80,1)*P(80,1)*P(80,1)=80*80*80=512,000 个结果,而不是 492,960 个结果。 )
  • 当然。出于某种原因,我专注于有 3 个文件并将其与从集合中选择 3 个项目混合在一起。无论哪种方式,我认为提问者不会很快将它们全部打印出来。 ;-)
  • 感谢自从我昨晚发布这个问题以来所有评论过的人。为了进一步澄清,我希望数组保持该顺序(我刚刚意识到我之前没有指定),但是使用当前代码,它会打印内存地址位置,而不是数组的内容。我将尝试一些建议的代码,如果它适合我​​,我会告诉你。
  • 这并没有说明什么。请提供您想要的输出。
【解决方案3】:

我通过作弊解决了我的最后一个格式化问题。我刚刚编辑了源文件并删除了所有的 \r 和 \n。

最终代码:

use Algorithm::Loops qw( NestedLoops );
use warnings;

open (FILE, app_txt);
 ($app = (<FILE>));
close (FILE);
my @app = split /,/, $app;

open (FILE, att1_txt);
 ($att1 = (<FILE>));
close (FILE);
my @att1 = split /,/, $att1;

open (FILE, att2_txt);
 ($att2 = (<FILE>));
close (FILE);
my @att2= split /,/, $att2;

my $iter = NestedLoops([ \@app, \@att1, \@att2 ]);
while ( my ($app, $att1, $att2) = $iter->() ) {
    open (my $fh, '>', 'test');
    print  $fh "$app $att1 $att2\n";
    close $fh;
}

print "done\n";

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-25
    • 1970-01-01
    • 2014-05-05
    • 2022-01-18
    相关资源
    最近更新 更多