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)
我可能会忽略一些非常明显的东西,但看不到,也不知道这样做的合理方法?
非常感谢您的帮助.
首先,defined @array和defined %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)