如何在不在Perl中嵌套foreach语句的情况下处理嵌套循环?

Spa*_*ace 5 perl nested-loops

我有一个Perl脚本,它嵌套foreach循环,如下所示.这需要很长时间:

#! /usr/bin/perl

use strict;
use warnings;

my @sites = ('a', 'b', 'c');
my @servers = ('A', 'B');
my @data_type = ("X", "Y", "Z");

foreach my $site (@sites) {
    foreach my $server_type (@servers) {
        foreach my $data (@data_type) {
            #statements
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

foreach像这样的嵌套语句需要很长时间,而且很难阅读而且不是很漂亮.谁能建议一个更好的方法来使用哈希或其他一些聪明的结构来编码这个结构?

bri*_*foy 6

使用我的Set :: CrossProduct模块,或使用Algorithm :: Loops.您不必创建硬编码的嵌套结构来处理这些问题.这两个模块都可以为您提供任意数量的数组.

use Set::CrossProduct;

my @sites = ('a', 'b', 'c');
my @servers = ('A', 'B');
my @data_type = ("X", "Y", "Z");

my $cross = Set::CrossProduct->new( 
    [ \@sites, \@servers, \@data_type ]
    );

while( my $tuple = $cross->get ) {
    print "@$tuple\n";
    }
Run Code Online (Sandbox Code Playgroud)

不仅如此,光标还为您提供了在迭代器中移动的方法,因此您不必将自己限制在当前组合中.您可以检查上一个和下一个组合,这可能对边界有用(例如下一个元组是不同服务器的位置).

注意那些想要在内存中创建所有组合的人.也没有必要这样做.


p00*_*0ya 3

我不明白你的问题是什么,但如果你习惯于 SQL 或其他东西,你可以使用通用笛卡尔积:

sub cartesian {
    my @C = map { [ $_ ] } @{ shift @_ };
    foreach (@_) {
        my @A = @$_;
        @C = map { my $n = $_; map { [ $n, @$_ ] } @C } @A;
    }
    return @C;
}

my @sites = ('a', 'b', 'c');
my @servers = ('A', 'B');
my @data_type = ("X", "Y", "Z");

foreach (cartesian(\@sites, \@servers, \@data_type)) {
    ($data, $server_type, $site) = @$_;
    print "$site $server_type $data\n";
}
Run Code Online (Sandbox Code Playgroud)

  • 更简单的是使用 CPAN 上提供的 `Set::CrossProduct`。 (2认同)
  • 不要这样做:您必须在内存中创建所有元组。:( (2认同)