在perl中的foreach循环中自动获取循环索引
如果我在Perl中有以下数组:
@x = qw(abc);
我用foreach
迭代它,然后$_
将引用数组中的当前元素 :
foreach (@x) { print; }
将打印:
abc
有没有类似的方式来获取当前元素的索引 ,而不需要手动更新计数器? 诸如:
foreach (@x) { print $index; }
其中$index
像$_
一样更新以产生输出:
012
就像codehead说的那样,你必须遍历数组索引而不是元素。 我比C样式的循环更喜欢这个变体:
for my $i (0 .. $#x) { print "$i: $x[$i]\n"; }
在5.10之前的Perl中,你可以说
#!/usr/bin/perl use strict; use warnings; my @a = qw/abcde/; 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来声明一个永远不会被重新初始化的variables(不像用我创build的variables)。 这可以让你将$index
variables保持在一个较小的范围内,但是会导致bug(如果你再次进入循环,它仍然会有最后一个值):
#!/usr/bin/perl use 5.010; use strict; use warnings; my @a = qw/abcde/; 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/abcde/; while (my ($index, $elem) = each @a) { say "At index $index I saw $elem"; }
但是需要注意的是:你对@a
允许做的事情有一些限制 ,而对它们进行迭代。
它现在不会帮助你,但在Perl 6中,你将能够说出来
#!/usr/bin/perl6 my @a = <abcd e>; for @a Z 0 .. Inf -> $elem, $index { say "at index $index, I saw $elem" }
Z
运算符将两个列表拉到一起(即,它从第一个列表中取一个元素,然后从第二个列表取一个元素,然后从第一个列表取一个元素,依此类推)。 第二个列表是一个惰性列表,其中包含从0到无穷大(至less在理论上)的每个整数。 -> $elem, $index
表示我们从压缩的结果中每次取两个值。 其余的应该看起来很正常(除非你不熟悉5.10的say
function)。
perldoc perlvar
似乎没有build议任何这样的variables。
不与foreach。 如果你肯定需要数组中的元素基数,使用“for”迭代器。
for($i=0;$i<@x;++$i) { print "Element at index $i is ",$x[$i],"\n"; }
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
不,你必须自己做一个计数器。 还有一个例子:
my $index; foreach (@x) { print $index++; }
当用于索引
my $index; foreach (@x) { print $x[$index]+$y[$index]; $index++; }
当然你可以使用local $index;
而不是my $index;
等等。
编辑 :根据第一个ysth的评论更新。
是。 我已经检查了很多书和其他博客…结论是,循环计数器没有系统variables。 我们必须做出自己的反应。 如我错了请纠正我。
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; }
另请参阅:
- 每个给自己(autobox)
-
perl5i
/ I3az /
那么有这样的方式:
use List::Rubyish; $list = List::Rubyish->new( [ qw<ab c> ] ); $list->each_index( sub { say "\$_=$_" } );
见List :: Rubyish
在大多数情况下,你不需要知道索引,你可以这样做
my @arr = (1, 2, 3); foreach (@arr) { $_++; } print join(", ", @arr);
在这种情况下,输出将是2,3,4,因为foreach为实际元素设置别名,而不仅仅是副本。
我已经尝试像….
@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 /abcd/; my $count; for (@array) { print "\n",$count++," $_"; } undef $count;