如何解决如何避免在Perl中使用“ eval”?
我有这样的代码:
my @e = ( '($i,$j,$k,$l)','($i,$l,$k)','($j,$i,'($k,$j)'
);
#
# Assign various sets of values to $i,$l
#
foreach ( @e ) {
my ($a,$b,$c,$d) = eval $_;
#
# Do calculations based on the values of $a,$d
#
所有操作均符合我的预期。但是像这样使用eval感觉很笨拙。我觉得必须有更好的方法遍历这四个值的六个排列。我尝试了各种方法,但没有找到任何有效的方法,因此我放弃使用eval。
解决方法
我可能会带潜艇。
my @e = (
sub { @_[ 0,1,2,3 ] },sub { @_[ 0,3,2 ] },sub { @_[ 1,sub { @_[ 2,1 ] },);
...
for (@e) {
my ( $a,$b,$c,$d ) = $_->($i,$j,$k,$l);
...
}
如果值已存在于数组中,则以上内容将简化为以下内容:
my @e = (
[ 0,3 ],[ 0,2 ],[ 1,[ 2,1 ],$d ) = @v[$_];
...
}
如果我们要处理更多的值,我会考虑使用编程方法来生成 pair 突变,但是我认为没有什么简单的方法值得。
,不要重新发明轮子。要遍历数组的所有排列,请使用为此目的编写的任何Perl模块,例如Algorithm::Permute(HåkonHægland的注释中指出了这一点)。
例如:
use Algorithm::Permute;
use feature qw( say );
my $perm = new Algorithm::Permute([$i,$l]);
while (@permutation = $perm->next) {
say join "\t",@permutation;
}
,
我不知道您到底想实现什么,但这可能会帮助您:
my @e = ( [$i,$l],[$i,$l,$k],[$j,$i,[$k,$j]
);
...
foreach (@e) {
my ($a,$d) = @$_;
...
@e
现在是一个数组引用数组。在foreach
循环中,$_
始终包含数组引用之一,而@$_
取消引用它,从而得到数组。
这在语义上略有不同,因为分配了$i
时,$j
,$k
,$l
和@e
仅被评估一次。可以,但是在您的应用程序中可能会出现问题。
如果您需要原始行为,则可以使用稍微复杂一些的解决方案来实现:
my @e = ( [\$i,\$j,\$k,\$l],[\$i,\$l,\$k],[\$j,\$i,[\$k,\$j]
);
...
foreach (@e) {
my ($a,$d) = map {$$_} @$_;
...
这意味着@e
拥有变量的引用,它们将被map {$$_}
取消引用。
顺便说一句,您应该考虑在foreach循环的主体中制作一个sub。
,我似乎可以从注释中收集到,$i $j $k $l
的值在foreach循环期间发生了变化,因此您需要使用它们的当前值。这就是eval()
解决方案有些疯狂的原因。
其他人建议了您未接受的解决方案,因此也许这是您所需要的。正如Donat在他的回答中所说,您可以使foreach循环成为子循环。这样,您就可以在没有@e
数组中间存储的情况下运行foreach循环。当然,这将取决于更改子内部的全局变量,这通常是一件坏事。
do_foreach($i,$l);
do_foreach($i,$k);
...etc
sub do_foreach {
my ($a,$d) = @_;
... do stuff
}
我怀疑您的问题来自代码其他地方的糟糕设计决策,否则它可能会从解决中受益。但是用给出的信息很难分辨。
,如果您确实只想处理示例代码中引用的那些排列,那么为什么不按以下说明进行处理(排列的平方数)呢?
注意:请更详细地说明您的问题以及可以运行的白色最小代码示例(不要忘记use strict; use warnings
-两行 magic 行,这些行有助于避免很多陷阱)
use strict;
use warnings;
use feature 'say';
my($i,$l) = (1..4);
my @e = ( [$i,$j]
);
do_work($_) for @e;
sub do_work {
my $aref = shift;
my @square = map { $_*$_ } @{$aref};
say join "\t",@square;
}
输出
1 4 9 16
1 9 4 16
1 16 4 9
4 9 1 16
4 16 1 9
9 16 1 4
,
我不确定为什么只有6个排列。请研究以下代码以解决您的问题。
use strict;
use warnings;
use feature 'say';
my @array = qw/a b c d/;
my $result = mutate(\@array);
say join "\t",@{$_} for @{$result};
sub mutate {
my $aref = shift;
my @data = @{$aref};
my @ret;
for ( 1..scalar @data ) {
my($c,@block) = @data;
for ( 1..scalar @block ) {
push @ret,[$c,@block];
my $t = pop @block;
unshift @block,$t;
}
@data = (@block,$c);
}
return \@ret;
}
输出
a b c d
a d b c
a c d b
b c d a
b a c d
b d a c
c d a b
c b d a
c a b d
d a b c
d c a b
d b c a
my @array = qw/a b c d e/;
的其他示例
a b c d e
a e b c d
a d e b c
a c d e b
b c d e a
b a c d e
b e a c d
b d e a c
c d e a b
c b d e a
c a b d e
c e a b d
d e a b c
d c e a b
d b c e a
d a b c e
e a b c d
e d a b c
e c d a b
e b c d a
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。