Perl 如何在不必重复代码的情况下执行两个不同的Foreach循环
我有一个散列数组和一个普通数组,这取决于环境(即用户在程序运行时选择的选项),其中只定义一个 演示问题的示例代码:Perl 如何在不必重复代码的情况下执行两个不同的Foreach循环,perl,foreach,code-duplication,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 "va
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);
}
}
}
正如您在上面的代码中所看到的,根据是否定义了@array
或是否定义了%hashofarray
,它将运行相应的if
语句
问题:
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);
}
}
}
但问题是,以下代码行在两个if
语句中重复:
call_subroutine($var1);
print "Something else is printed";
call_anothersubroutine($var1);
call_differentsubroutine($var1);
显然,如果这些foreach
循环包含大量代码,这将意味着大量代码将被复制
当涉及到foreach
循环时,是否有任何方法/可以避免这种代码重复的最佳方法是什么
实际上,是否有一种方法可以执行以下操作:(我很清楚此代码不起作用,但解释了我试图实现的目标)
我可能忽略了一些显而易见的事情,但看不到一种合乎逻辑的方法来做到这一点?首先,
defined@array
和defined%hashofarrays
是错误的。它们总是被定义的。您希望if(@array)
和if(key%hashofarrays)
测试它们是否包含元素。您甚至应该得到一个警告defined(@array)已弃用
您需要的是另一个子例程
sub loop_body { # just use some better name!
my ($var) = @_;
call_subroutine($var);
print "Something else is printed";
call_anothersubroutine($var);
call_differentsubroutine($var);
}
然后:
您还可以使用回调使解决方案更加灵活:
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);
}
}
然后:
首先,defined@array
和defined%hashofarrays
是错误的。它们总是被定义的。您希望if(@array)
和if(key%hashofarrays)
测试它们是否包含元素。您甚至应该得到一个警告defined(@array)已弃用
您需要的是另一个子例程
sub loop_body { # just use some better name!
my ($var) = @_;
call_subroutine($var);
print "Something else is printed";
call_anothersubroutine($var);
call_differentsubroutine($var);
}
然后:
您还可以使用回调使解决方案更加灵活:
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);
}
}
然后:
使用另一个函数可能会有所帮助
if (@array) {
my_func(\@array);
}
if (%hashofarrays) {
foreach my $key (keys %hashofarrays) {
print "the key is: $key\n";
my_func($hashofarrays{$key});
}
}
sub my_func {
my ($arr) = @_;
foreach my $var1 (@$arr) {
call_subroutine($var1);
print "Something else is printed";
call_anothersubroutine($var1);
call_differentsubroutine($var1);
}
}
使用另一个函数可能会有所帮助
if (@array) {
my_func(\@array);
}
if (%hashofarrays) {
foreach my $key (keys %hashofarrays) {
print "the key is: $key\n";
my_func($hashofarrays{$key});
}
}
sub my_func {
my ($arr) = @_;
foreach my $var1 (@$arr) {
call_subroutine($var1);
print "Something else is printed";
call_anothersubroutine($var1);
call_differentsubroutine($var1);
}
}
正如阿蒙所说,if(defined@array)
是错误的,但我甚至不会为if(@array)
而烦恼,除非你有一个else
。您可以直接转到(@array)
的,如果@array
为空,它将迭代零次,基本上就像if
一样跳过循环
这样看来,您希望对@array
中的每个元素和%数组散列中的每个键执行相同的操作,对吗?您甚至不需要子系统
:
for (@array, map { @$_ } values %hashofarrays) {
my $var1 = $_;
print "var is: $var1\n";
call_subroutine($var1);
print "Something else is printed";
call_anothersubroutine($var1);
call_differentsubroutine($var1);
}
编辑:修改代码,以循环遍历%hashofarrays
中数组的内容,而不是其键。这仍然与初始问题中的代码不完全匹配,因为它在hoa上循环时打印$var1
,而不是打印哈希键,但看起来OP的实际用例很有可能除了索引到哈希之外不使用任何键,在这种情况下,它实际上并不需要(因为我们可以使用值%hoa
。正如阿蒙所说,if(defined@array)
是错误的,但我甚至不会为if(@array)
而烦恼,除非你有一个else
。你可以直接转到for(@array)
并且,如果@array
为空,它将迭代零次,本质上就像if
一样跳过循环
这样看来,您希望对@array
中的每个元素和%数组散列中的每个键执行相同的操作,对吧?您甚至不需要子:
for (@array, map { @$_ } values %hashofarrays) {
my $var1 = $_;
print "var is: $var1\n";
call_subroutine($var1);
print "Something else is printed";
call_anothersubroutine($var1);
call_differentsubroutine($var1);
}
编辑:修改代码,以循环%hashofarrays
中数组的内容,而不是其键。这仍然与初始问题中的代码不完全匹配,因为它在循环hoa时打印$var1
,而不是打印哈希键,但看起来很有可能's的实际用例除了索引到散列中之外不使用键,在这种情况下,无论如何都不需要它(因为我们可以使用值%hoa
).这个答案可能会有帮助:在数组和哈希上使用定义的是不推荐的。@perl用户是不推荐的。这个答案可能会有帮助:在数组和哈希上使用定义的是不推荐的。@perl用户是不推荐的。@
而不是local$\u=$var;
@mpapec我考虑过这一点,但我认为尽可能使用显式的词汇循环变量是很重要的。显式的local
也是一种强有力的表达方式,“我希望让我调用的subs能够看到这一点。”考虑到OP对Perl的了解,应该避免隐式行为。我不久前对手动本地化$\uuu
感到愤怒,但不记得为什么应该避免隐式行为。我将尝试查找那篇文章。@mpapec我对这样一篇文章感兴趣。但你确定你没有将其与词法$\u
混淆吗?现在my$\
与5.10中的其他错误一起被劝阻。也许(@{my$var=$\}
的而不是local$\=$var;
@mpapec我考虑过这一点,但我认为尽可能使用显式的词汇循环变量是很重要的。显式的local
也是一种强有力的表达方式“我希望让我调用的sub可以看到这一点。”考虑到OP对Perl的了解,应该避免隐式行为。我不久前对$\uuuu
的手动本地化很感兴趣,但不记得为什么应该避免。我将试着找到那篇文章。@mppec我对这篇文章很感兴趣。Bu