Search code examples
perlnested-loops

How can I handle nested looping without nesting foreach statements in Perl?


I have a Perl script which nests foreach loops as seen below. It takes a long time:

#! /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
        }
    }
}

Nesting foreach statements like this takes a long time and it's hard to read and not very pretty. Can anyone suggest a better way to code this structure using hashes, or some other clever structure?


Solution

  • I don't see what your problem is, but you could use a generic Cartesian product if you are used to SQL or something:

    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";
    }