Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 223
Space Avatar asked Aug 26 '09 06:08

Space


People also ask

How do I break a nested loop in Perl?

Perl last Statement with LABEL If you want to exit a nested loop, put a label in the outer loop and pass label to the last statement. If LABEL is specified with last statement, execution drops out of the loop encountering LABEL instead of currently enclosing loop.

Can you nest foreach loops?

An important feature of foreach is the %:% operator. I call this the nesting operator because it is used to create nested foreach loops. Like the %do% and %dopar% operators, it is a binary operator, but it operates on two foreach objects.

Should you avoid nested for loops?

Nested loops are frequently (but not always) bad practice, because they're frequently (but not always) overkill for what you're trying to do. In many cases, there's a much faster and less wasteful way to accomplish the goal you're trying to achieve.

What is the purpose of the foreach loop construct in Perl?

A foreach loop is used to iterate over a list and the variable holds the value of the elements of the list one at a time. It is majorly used when we have a set of data in a list and we want to iterate over the elements of the list instead of iterating over its range.


1 Answers

Use my Set::CrossProduct module, or use Algorithm::Loops. You shouldn't have to create hard-coded, nested structures to deal with these issues. Both of those modules can do it for you for an arbitrary number of arrays.

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

Not only that, but the cursor gives you ways to move around in the iterator so you don't have to limit yourself to the current combination. You can inspect the previous and next combinations, which might be useful for boundaries (like where the next tuple is a different server).

Watch out for people who want to create all of the combinations in memory. There's no need to do that either.

like image 83
brian d foy Avatar answered Oct 07 '22 00:10

brian d foy