在perl中自动获取foreach循环中的循环索引

时间:2009-06-10 09:56:30

标签: perl foreach

如果我在Perl中有以下数组:

@x = qw(a b c);

我用foreach迭代它,然后$_将引用数组中的当前元素

foreach (@x) {
    print;
}

将打印:

abc

是否有类似的方法来获取当前元素的索引,而无需手动更新计数器?例如:

foreach (@x) {
    print $index;
}

其中$index更新为$_以产生输出:

012

13 个答案:

答案 0 :(得分:102)

就像codehead所说的那样,你必须迭代数组索引而不是它的元素。我更喜欢这种变体而不是C风格的循环:

for my $i (0 .. $#x) {
    print "$i: $x[$i]\n";
}

答案 1 :(得分:42)

在5.10之前的Perl中,你可以说

#!/usr/bin/perl

use strict;
use warnings;

my @a = qw/a b c d e/;

my $index;
for my $elem (@a) {
    print "At index ", $index++, ", I saw $elem\n";
}

#or

for my $index (0 .. $#a) {
    print "At index $index I saw $a[$elem]\n";
}    

在Perl 5.10中,您使用state来声明一个永远不会重新初始化的变量(与使用my创建的变量不同)。这允许您将$index变量保留在较小的范围内,但可能导致错误(如果您第二次进入循环,它仍将具有最后一个值):

#!/usr/bin/perl

use 5.010;
use strict;
use warnings;

my @a = qw/a b c d e/;

for my $elem (@a) {
    state $index;
    say "At index ", $index++, ", I saw $elem";
}

在Perl 5.12中你可以说

#!/usr/bin/perl

use 5.012; #this enables strict
use warnings;

my @a = qw/a b c d e/;

while (my ($index, $elem) = each @a) {
    say "At index $index I saw $elem";
}

但请注意:@a在使用each进行迭代时,#!/usr/bin/perl6 my @a = <a b c d e>; for @a Z 0 .. Inf -> $elem, $index { say "at index $index, I saw $elem" } 允许您使用restrictions。{/ p>

现在对你没有帮助,但在Perl 6中你可以说

Z

-> $elem, $index运算符将两个列表压缩在一起(即,它从第一个列表中获取一个元素,然后从第二个列表中获取一个元素,然后从第一个中获取一个元素,依此类推)。第二个列表是lazy列表,其中包含从0到无穷大的每个整数(至少在理论上)。 {{1}}表示我们从zip结果中一次取两个值。其余的应该看起来很正常(除非你不熟悉5.10中的say函数)。

答案 2 :(得分:23)

perldoc perlvar似乎没有暗示任何此类变量。

答案 3 :(得分:7)

不是foreach。 如果你肯定需要数组中的元素基数,请使用'for'迭代器。

for($i=0;$i<@x;++$i) {
  print "Element at index $i is ",$x[$i],"\n";
}

答案 4 :(得分:6)

Perl版本5.14.4

可以使用while循环完成(foreach不支持此操作)

my @arr = (1111, 2222, 3333);

while (my ($index, $element) = each(@arr))
{
   # You may need to "use feature 'say';"
   say "Index: $index, Element: $element";
}

输出:

Index: 0, Element: 1111
Index: 1, Element: 2222
Index: 2, Element: 3333

答案 5 :(得分:4)

不,你必须自己制作一个柜台。又一个例子:

my $index;
foreach (@x) {
    print $index++;
}

用于索引

my $index;
foreach (@x) {
    print $x[$index]+$y[$index];
    $index++;
}

当然,您可以使用local $index;代替my $index;等等。

编辑:根据第一个ysth的评论更新。

答案 6 :(得分:4)

是。我检查过这么多书和其他博客......结论是,循环计数器没有系统变量。我们要做自己的柜台。如果我错了,请纠正我。

答案 7 :(得分:2)

autobox::Core提供了许多方便的for方法:

use autobox::Core;

['a'..'z']->for( sub{
    my ($index, $value) = @_;
    say "$index => $value";
});

或者看一下迭代器模块,例如:Array::Iterator

use Array::Iterator;

my $iter = Array::Iterator->new( ['a'..'z'] );
while ($iter->hasNext) {
    $iter->getNext;
    say $iter->currentIndex . ' => ' . $iter->current;
}

另见:

/ I3az /

答案 8 :(得分:1)

有这样的方式:

use List::Rubyish;

$list = List::Rubyish->new( [ qw<a b c> ] );
$list->each_index( sub { say "\$_=$_" } );

请参阅List::Rubyish

答案 9 :(得分:1)

哦,可以! (有点,但您不应该)。标量上下文中的each(@array)为您提供数组的当前索引。

@a = (a..z);
for (@a){ 
  print each(@a) . "\t" . $_ . "\n"; 
}

此处each(@a)在标量上下文中,仅返回索引,而不返回该索引处的值。由于我们处于for循环中,因此我们已经在$ _中拥有了值。 While-Each循环中经常使用相同的机制。同样的问题。

如果再次执行for(@a),问题就来了,索引没有回到您期望的0,它是undef后跟0,1,2 ...一个数字。 each()的perldoc表示为避免此问题,请使用for循环来跟踪索引。 https://perldoc.perl.org/functions/each.html

基本上:

for(my $i=0; $i<=$#a; $i++){
  print "The Element at $i is $a[$i]\n";
}

我是替代方法的粉丝

my $index=0;
for (@a){
  print "The Element at $index is $a[$index]\n";
  $index++;
}

答案 10 :(得分:0)

在大多数情况下你不需要知道索引,你可以这样做

my @arr = (1, 2, 3);
foreach (@arr) {
    $_++;
}
print join(", ", @arr);

在这种情况下,输出将是 2,3,4 ,因为foreach为实际元素设置别名,而不仅仅是副本。

答案 11 :(得分:0)

我试过......

@array = qw /tomato banana papaya potato/;                  # example array
my $count;                                                  # local variable initial value will be 0
print "\nBefore For loop value of counter is $count";       # just printing value before entering in   loop

for (@array) { print "\n",$count++," $_" ; }                # string and variable seperated by comma to 
                                                            # execute the value and print
undef $count;                                               # undefining so that later parts again it will
                                                            # be reset to 0

print "\nAfter for loop value of counter is $count";        # checking the counter value after for loop.

简而言之..

@array = qw /a b c d/;
my $count;
for (@array) { print "\n",$count++," $_"; }
undef $count;

答案 12 :(得分:0)

请考虑:

print "Element at index $_ is $x[$_]\n" for keys @x;