developer tip

펄의 foreach 루프에서 자동으로 루프 인덱스를 얻습니다.

optionbox 2020. 10. 18. 09:19
반응형

펄의 foreach 루프에서 자동으로 루프 인덱스를 얻습니다.


Perl에 다음 배열이있는 경우 :

@x = qw(a b c);

을 사용하여 반복 foreach한 다음 배열 $_의 현재 요소참조합니다 .

foreach (@x) {
    print;
}

인쇄됩니다 :

abc

카운터를 수동으로 업데이트하지 않고 현재 요소 인덱스 를 얻는 유사한 방법이 있습니까? 다음과 같은 것 :

foreach (@x) {
    print $index;
}

출력을 산출하기 위해 $index업데이트 되는 위치 $_:

012

코드 헤드가 말했듯이 요소 대신 배열 인덱스를 반복해야합니다. C 스타일 for 루프보다이 변형을 선호합니다.

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

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에서는 상태사용하여 다시 초기화되지 않는 변수를 선언합니다 ( 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";
}

그러나 경고하십시오. .NET을 사용하여 반복 하는 동안 수행 할 수있는 작업에 제한 이 있습니다 .@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오퍼레이터 함께 두리스트를 참아 (즉, 그 다음에, 하나 개의 원소 번째부터 다음 첫 번째 목록에서 등 처음부터 하나 개의 요소를 하나 개의 원소 소요). 두 번째 목록은 0에서 무한대까지 (적어도 이론적으로는) 모든 정수를 포함 하는 게으른 목록입니다. -> $elem, $index우리가 우편의 결과에서 한 번에 두 개의 값을 복용하고 있다고 말한다. 나머지는 정상적으로 보일 것입니다 ( say아직 5.10 기능에 익숙하지 않은 경우).


perldoc perlvar 그러한 변수를 제안하지 않는 것 같습니다.


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++;
}

And of course you can use local $index; instead my $index; and so and so.

EDIT: Updated according to first ysth's comment.


Yes. I have checked so many books and other blogs... conclusion is, there is no system variable for the loop counter. we have to make our own counter. correct me if i m wrong.


autobox::Core provides among many more things a handy for method:

use autobox::Core;

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

Alternatively have a look at an iterator module, for eg: Array::Iterator

use Array::Iterator;

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

Also see:

/I3az/


Oh yes you can! (sort of, but you shouldn't). each(@array) in scalar context gives you the current index of the array.

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

Here each(@a) is in a scalar context and returns only the index, not the value at that index. Since we're in a for loop, we have the value in $_ already. The same mechanism is often used in a While-Each loop. Same problem.

The problem comes if you do for(@a) again, the index isn't back to 0 like you'd expect, it's undef followed by 0,1,2... one count off. The perldoc of each() says to avoid this issue, use a for loop to track the index. https://perldoc.perl.org/functions/each.html

Basically:

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

I'm a fan of the alternate method:

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

Well there is this way:

use List::Rubyish;

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

see List::Rubyish


You shouldn't need to know the index in most circumstances, you can do this

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

In this case, the output would be 2, 3, 4 as foreach sets an alias to the actual element, not just a copy.


I have tried like....

@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.

in short..

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

Please consider:

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

참고URL : https://stackoverflow.com/questions/974656/automatically-get-loop-index-in-foreach-loop-in-perl

반응형