是否可以在Perl foreach循环中分配两个变量?

joh*_*lak 13 arrays variables perl foreach loops

是否可以在Perl foreach循环中为数组中的两个变量分配相同的数据?

我使用Perl 5,我想我在Perl 6中遇到了一些东西.

像这样的东西:

my $var1;
my $var2;

foreach $var1,$var2 (@array){...}
Run Code Online (Sandbox Code Playgroud)

Dav*_*man 14

它不是Perl 5核心语言,但是List :: Util有一个pairs应该足够接近的函数(以及许多其他pair...函数可能更方便,具体取决于你在循环中做的事情):

#!/usr/bin/env perl    

use strict;
use warnings;
use 5.010;

use List::Util 'pairs';

my @list = qw(a 1 b 2 c 3);

for my $pair (pairs @list) {
  my ($first, $second) = @$pair;
  say "$first => $second";
}
Run Code Online (Sandbox Code Playgroud)

输出:

a => 1
b => 2
c => 3
Run Code Online (Sandbox Code Playgroud)

  • List :: Util是Perl 5.7.3以来的核心模块.因此可以假设它是安装的. (4认同)
  • @BarneySchmale - 是的,我不太清楚如何清楚地说出来.它是核心_distribution_的一部分(你不必从CPAN安装),但不是核心_language_的一部分(你必须明确地"使用"模块).我愿意接受建议(或编辑),以便在答案中说出更好的方法. (3认同)

tch*_*ist 9

最简单的方法是使用一个while循环,splice每次调用数组的前两个元素,

while (my($var1, $var2) = splice(@array, 0, 2)) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

然而,与之不同的是foreach,这在原始数组上不断进行双重移位,所以当你完成时,数组是空的.此外,分配的变量是副本,而不是别名foreach.

如果您不喜欢,可以使用C风格的for循环:

for (my $i = 0; $i < @array; $i += 2) {
     my($var1, $var2) = @array[$i, $i+1];
     ...
}
Run Code Online (Sandbox Code Playgroud)

这使得数组保持不变,但不允许您按照方式更新它foreach.为此,您需要直接处理数组.

my @pairlist = (
    fee => 1,
    fie => 2,
    foe => 3,
    fum => 4,
);

for (my $i = 0; $i < @pairlist; $i += 2) {
    $pairlist[ $i + 0 ] x= 2;
    $pairlist[ $i + 1 ] *= 2;
}

print "Array is @pairlist\n";
Run Code Online (Sandbox Code Playgroud)

打印出:

Array is feefee 2 fiefie 4 foefoe 6 fumfum 8
Run Code Online (Sandbox Code Playgroud)

如果你努力尝试,你可以把它们变成别名变量,但它可能不值得:

my @kvlist = ( 
    fee => 1,
    fie => 2,
    foe => 3,
    fum => 4,
);

for (my $i = 0; $i < @kvlist; $i += 2) { 
    our  ($key, $value);
    local(*key, $value) = \@kvlist[ $i, $i + 1 ];
    $key   x= 2;
    $value *= 2;
}

print "Array is @kvlist\n";
Run Code Online (Sandbox Code Playgroud)

打印出预期更改的数组:

Array is feefee 2 fiefie 4 foefoe 6 fumfum 8
Run Code Online (Sandbox Code Playgroud)

请注意,由所提供的对表::成对模块,这不过是非常最近添加到核心列表::的Util模块(所以你可能无法使用),仍然没有给你的别名:

use List::Util 1.29 qw(pairs);

my @pairlist = (
    fee => 1,
    fie => 2,
    foe => 3,
    fum => 4,
);

for my $pref (pairs(@pairlist)) {
    $pref->[0] x= 2;
    $pref->[1] *= 2;
}

print "Array is @pairlist\n";
Run Code Online (Sandbox Code Playgroud)

仅打印出来:

Array is fee 1 fie 2 foe 3 fum 4
Run Code Online (Sandbox Code Playgroud)

所以它根本没有改变阵列.哎呀.:(

当然,如果这是一个真正的哈希值,你可以简单地将值加倍:

for my $value (values %hash) { $value *= 2 }
Run Code Online (Sandbox Code Playgroud)

有效的原因是因为它们是实际哈希值的别名.

您无法更改密钥,因为它们是不可变的.但是,您可以轻松地创建一个新哈希,它是旧版本的更新副本:

my %old_hash = (
    fee => 1,
    fie => 2,
    foe => 3,
    fum => 4,
);

my %new_hash;    
@new_hash{ map { $_ x 2 } keys   %old_hash } = 
           map { $_ * 2 } values %old_hash;

print "Old hash is: ", join(" " => %old_hash), "\n";
print "New hash is: ", join(" " => %new_hash), "\n";
Run Code Online (Sandbox Code Playgroud)

那输出

Old hash is: foe 3 fee 1 fum 4 fie 2
New hash is: foefoe 6 fiefie 4 fumfum 8 feefee 2
Run Code Online (Sandbox Code Playgroud)