我有这样的代码:
my @e = ( '($i,$j, $k,$l)', '($i,$k, $j,$l)', '($i,$l, $j,$k)',
'($j,$k, $i,$l)', '($j,$l, $i,$k)', '($k,$l, $i,$j)'
);
#
# Assign various sets of values to $i,$j,$k,$l
#
foreach ( @e ) {
my ($a,$b, $c,$d) = eval $_;
#
# Do calculations based on the values of $a,$b,$c,$d
#
一切都如我所愿。但这样使用eval感觉很笨拙。我觉得必须有一种更好的方法来循环这四个值的六个排列。我尝试了各种方法,但都没有找到有效的方法,所以我放弃了使用eval。
我可能会选择subs。
my @e = (
sub { @_[ 0,1, 2,3 ] },
sub { @_[ 0,2, 1,3 ] },
sub { @_[ 0,3, 1,2 ] },
sub { @_[ 1,2, 0,3 ] },
sub { @_[ 1,3, 0,2 ] },
sub { @_[ 2,3, 0,1 ] },
);
...
for (@e) {
my ( $a,$b, $c,$d ) = $_->($i, $j, $k, $l);
...
}
如果值已经在一个数组中,则以上简化为以下内容:
my @e = (
[ 0,1, 2,3 ],
[ 0,2, 1,3 ],
[ 0,3, 1,2 ],
[ 1,2, 0,3 ],
[ 1,3, 0,2 ],
[ 2,3, 0,1 ],
);
...
for (@e) {
my ( $a,$b, $c,$d ) = @v[$_];
...
}
如果我们要处理更多的值,我会考虑一种程序化的方法来生成对突变,但我想不出有价值的简单方法。
不要重新发明轮子。要循环遍历数组的所有排列,请使用为此目的编写的任何Perl模块,例如Algorithm::Permute(Håkon Hægland在评论中指出了这一点(。
例如:
use Algorithm::Permute;
use feature qw( say );
my $perm = new Algorithm::Permute([$i, $j, $k, $l]);
while (@permutation = $perm->next) {
say join "t", @permutation;
}
我不知道你到底想实现什么,但这可能会对你有所帮助:
my @e = ( [$i,$j, $k,$l], [$i,$k, $j,$l], [$i,$l, $j,$k],
[$j,$k, $i,$l], [$j,$l, $i,$k], [$k,$l, $i,$j]
);
...
foreach (@e) {
my ($a,$b, $c,$d) = @$_;
...
@e
现在是数组引用的数组。在foreach
循环中,$_
始终包含一个数组引用,而@$_
取消引用它,从而生成数组。
这具有略微不同的语义,因为当分配@e
时,$i
、$j
、$k
和$l
将仅被评估一次。这可能没问题,但在您的应用程序中可能会出现问题。
如果你需要你的原始行为,你可以使用一个稍微复杂一点的解决方案:
my @e = ( [$i,$j, $k,$l], [$i,$k, $j,$l], [$i,$l, $j,$k],
[$j,$k, $i,$l], [$j,$l, $i,$k], [$k,$l, $i,$j]
);
...
foreach (@e) {
my ($a,$b, $c,$d) = map {$$_} @$_;
...
这意味着,@e
保持对变量的引用,并且它们将被map {$$_}
取消引用。
顺便说一句,你应该考虑用前臂的身体做一个小循环。
我似乎能够从注释中了解到,$i $j $k $l
的值在foreach循环期间会发生变化,您需要使用它们的当前值。这就是eval()
解决方案有些疯狂的原因。
其他人提出了你没有接受的解决方案,所以这可能是你需要的。正如多纳特在回答中所说,你可以做一个前臂环的子集。通过这种方式,您可以在@e
数组中不使用中间存储的情况下运行foreach循环。当然,这将依赖于改变子内部的全局变量,这通常是一件坏事。
do_foreach($i, $j, $k, $l);
do_foreach($i, $k, $j, $l);
do_foreach($i, $l, $j, $k);
...etc
sub do_foreach {
my ($a, $b, $c, $d) = @_;
... do stuff
}
我怀疑您的问题来自于代码中其他地方的糟糕设计决策,否则它可能会从解决中受益。但根据所提供的信息很难判断。
如果您确实只想处理样本代码中引用的排列,那么为什么不按以下方式处理呢(排列的平方数(?
注意:请详细说明您的问题,以及可以运行的白色最小代码示例(不要忘记use strict; use warnings
——两行魔术,有助于避免许多陷阱(
use strict;
use warnings;
use feature 'say';
my($i,$j,$k,$l) = (1..4);
my @e = ( [$i,$j, $k,$l], [$i,$k, $j,$l], [$i,$l, $j,$k],
[$j,$k, $i,$l], [$j,$l, $i,$k], [$k,$l, $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