Perl - 如何在不重复代码的情况下执行两个不同的Foreach循环

per*_*ser 1 perl foreach code-duplication

我有一个问题,我希望有人可以阐明......

我有一个数组散列和一个普通数组,具体取决于具体情况(即用户在程序运行时选择的选项),只定义其中一个.

用于演示问题的示例代码:

my %hashofarrays;
my @array;

#...
#Some code between here where either %hashofarrays or @array gets defined
#...

if (defined @array) {

    foreach my $var1 (@array) {
        print "var1 is: $var1\n";
        call_subroutine($var1);
        print "Something else is printed";
        call_anothersubroutine($var1);
        call_differentsubroutine($var1);
    }

} 

if (defined %hashofarrays) {

    foreach my $key (keys %hashofarrays) {
        print "the key is: $key\n";
        foreach my $var1 (@{$hashofarrays{$key}}) {
            call_subroutine($var1);
            print "Something else is printed";
            call_anothersubroutine($var1);
            call_differentsubroutine($var1);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

正如您在上面的代码中所看到的,取决于是否@array已定义或是否%hashofarrays已定义,它将运行相应的if语句.

问题:

但问题是,以下几行代码在两个if语句中都是重复的:

    call_subroutine($var1);
    print "Something else is printed";
    call_anothersubroutine($var1);
    call_differentsubroutine($var1);
Run Code Online (Sandbox Code Playgroud)

显然,如果这些foreach循环包含大量代码,那就意味着会复制大量代码.

有没有什么方法/什么是最好的方法可以避免这种重复的代码到foreach循环?

实际上,有没有办法做类似以下的事情:(我很清楚这段代码不起作用,但解释了我想要实现的目标)

if (defined @array) {
    foreach my $var1 (@array) {
} elsif (defined %hashofarrays) {
    foreach my $key (keys %hashofarrays) {
        print "the key is: $key\n";
        foreach my $var1 (@{$hashofarrays{$key}}) {

} #ending bracket of if statement

        call_subroutine($var1);
        print "Something else is printed";
        call_anothersubroutine($var1);
        call_differentsubroutine($var1); 

}  #ending bracket of whatever foreach loop is used
Run Code Online (Sandbox Code Playgroud)

我可能会忽略一些非常明显的东西,但看不到,也不知道这样做的合理方法?

非常感谢您的帮助.

amo*_*mon 5

首先,defined @arraydefined %hashofarrays错误的.它们总是被定义的.您想要if (@array)if (keys %hashofarrays)测试它们是否包含元素.你甚至应该得到一个警告defined(@array) is deprecated!

你想要的是另一个子程序.

sub loop_body {  # just use some better name!
  my ($var) = @_;
  call_subroutine($var);
  print "Something else is printed";
  call_anothersubroutine($var);
  call_differentsubroutine($var);
}
Run Code Online (Sandbox Code Playgroud)

然后:

if (@array) {
    foreach my $var1 (@array) {
        print "var1 is: $var1\n";
        loop_body($var1);
    }
} elsif (keys %hashofarrays) {
    foreach my $key (keys %hashofarrays) {
        print "the key is: $key\n";
        foreach my $var1 (@{$hashofarrays{$key}}) {
            loop_body($var1)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您还可以使用回调来使您的解决方案更加灵活:

 sub loop_with_cb {
   my $cb = shift;
   for my $var (@_) {
     if ($cb) {
       local $_ = $var; # make $_ visible to the callback
       $cb->($var);
     }
     call_subroutine($var);
     print "Something else is printed";
     call_anothersubroutine($var);
     call_differentsubroutine($var);
   }
 }
Run Code Online (Sandbox Code Playgroud)

然后:

if (@array) {
    loop_with_cb(
      sub { print "var1 is: $_\n" },
      @array,
    );
} elsif (keys %hashofarrays) {
    foreach my $key (keys %hashofarrays) {
        print "the key is: $key\n";
        loop_with_cb(undef, @{ $hashofarrays{$key} });
    }
}
Run Code Online (Sandbox Code Playgroud)