web-dev-qa-db-ja.com

perlのforeachループでループインデックスを自動的に取得します

Perlに次の配列がある場合:

@x = qw(a b c);

foreachで繰り返し処理すると、$_は配列内の現在のelementを参照します。

foreach (@x) {
    print;
}

印刷されます:

abc

手動でカウンターを更新せずに、現在の要素のindexを取得する同様の方法はありますか?次のようなもの:

foreach (@x) {
    print $index;
}

$index$_のように更新され、出力が生成されます。

012
75
Nathan Fellman

コードヘッドが言ったように、要素の代わりに配列インデックスを反復処理する必要があります。私はこのバリアントをCスタイルのforループよりも好みます。

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

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変数は小さいスコープですが、バグを引き起こす可能性があります(2回目にループに入ると、最後の値が保持されます)。

#!/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";
}

ただし、注意してください: restrictions を使用すると、@aeachで繰り返し処理します。

今では役に立ちませんが、Perl 6では次のように言うことができます。

#!/usr/bin/Perl6

my @a = <a b c d e>;
for @a Z 0 .. Inf -> $elem, $index {
    say "at index $index, I saw $elem"
}

Z演算子は、2つのリストを一緒に圧縮します(つまり、最初のリストから1つの要素を取得し、2番目のリストから1つの要素を取得し、最初のリストから1つの要素を取得します)。 2番目のリストは lazy リストであり、0から無限までのすべての整数を含んでいます(少なくとも理論的には)。 -> $elem, $indexは、Zipの結果から一度に2つの値を取得していることを示しています。残りはあなたに普通に見えるはずです(まだ5.10の say 関数に慣れていない限り)。

43
Chas. Owens

perldoc perlvarは、そのような変数を示唆していないようです。

23

Foreachではありません。配列内の要素のカーディナリティが確実に必要な場合は、「for」反復子を使用します。

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

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
7
Venkata Raju

いいえ、独自のカウンターを作成する必要があります。さらに別の例:

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

インデックス作成に使用される場合

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

そしてもちろん、local $index;代わりにmy $index;など。

[〜#〜] edit [〜#〜]:最初のysthのコメントに従って更新されました。

はい。私は非常に多くの本や他のブログをチェックしました...結論は、ループカウンター用のシステム変数はありません。独自のカウンターを作成する必要があります。私が間違っているなら私を修正してください。

4
surendra ben

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 /

2
draegtun

さて、この方法があります:

use List::Rubyish;

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

List :: Rubyish を参照してください

1
Axeman

はい、できます! (並べ替えますが、すべきではありません)。スカラーコンテキストのeach(@array)は、配列の現在のインデックスを提供します。

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

ここで、each(@a)はスカラーコンテキストにあり、そのインデックスの値ではなく、インデックスのみを返します。 forループにいるので、すでに$ _に値があります。 While-Eachループでも同じメカニズムがよく使用されます。同じ問題。

もう一度for(@a)を実行すると問題が発生します。インデックスは期待どおりに0に戻らず、undefの後に0,1,2 ...が1つカウントされます。 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++;
}
_
1
Able Mac

私は…のようにしてみました.

@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;
0
surendra ben

考えてください:

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

ほとんどの場合、インデックスを知る必要はありません。これを行うことができます

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

この場合、foreachは単なるコピーではなく実際の要素にエイリアスを設定するため、出力は2、3、4になります。

0