wake-up-neo.com

holen Sie sich automatisch den Schleifenindex in der foreach-Schleife in Perl

Wenn ich das folgende Array in Perl habe:

@x = qw(a b c);

und ich iteriere mit foreach darüber, dann verweist $_ auf das aktuelle element im Array:

foreach (@x) {
    print;
}

wird drucken:

abc

Gibt es einen ähnlichen Weg, um den Index des aktuellen Elements abzurufen, ohne einen Zähler manuell zu aktualisieren? Etwas wie:

foreach (@x) {
    print $index;
}

wobei $index wie $_ aktualisiert wird, um die Ausgabe zu erhalten:

012
70
Nathan Fellman

Wie Codehead bereits sagt, müssten Sie statt der Elemente die Array-Indizes durchlaufen. Ich bevorzuge diese Variante dem C-Stil für die Schleife:

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

In Perl vor 5.10 können Sie sagen

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

In Perl 5.10 verwenden Sie state , um eine Variable zu deklarieren, die niemals neu initialisiert wird (im Gegensatz zu solchen, die mit my erstellt werden). Auf diese Weise können Sie die Variable $index in einem kleineren Bereich halten, jedoch zu Fehlern führen (wenn Sie die Schleife ein zweites Mal eingeben, hat sie immer noch den letzten Wert):

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

In Perl 5.12 kann man sagen

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

Aber seien Sie gewarnt: Es gibt einschränkungen , was Sie mit @a machen dürfen, während Sie mit each iterieren.

Es wird dir jetzt nicht helfen, aber in Perl 6 kannst du sagen

#!/usr/bin/Perl6

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

Der Z-Operator zippt die beiden Listen zusammen (d. H. Er nimmt ein Element aus der ersten Liste, dann ein Element aus der zweiten Liste, dann ein Element aus der ersten Liste usw.). Die zweite Liste ist eine Lazy - Liste, die jede ganze Zahl von 0 bis unendlich (zumindest theoretisch) enthält. Der -> $elem, $index sagt aus, dass wir jeweils zwei Werte aus dem Ergebnis des Zip-Werts nehmen. Der Rest sollte für Sie normal aussehen (es sei denn, Sie kennen die Funktion say aus 5.10 noch nicht).

42
Chas. Owens

perldoc perlvar scheint keine solche Variable vorzuschlagen.

23

Nicht bei foreach . Wenn Sie definitiv das Element cardinality im Array benötigen, verwenden Sie einen "for" -Iterator.

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

Perl-Version 5.14.4

Kann mit while loop gemacht werden (foreach unterstützt dies nicht)

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

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

Ausgabe:

Index: 0, Element: 1111
Index: 1, Element: 2222
Index: 2, Element: 3333
5
Venkata Raju

Ja. Ich habe so viele Bücher und andere Blogs geprüft ... Fazit: Es gibt keine Systemvariable für den Schleifenzähler. Wir müssen unseren eigenen Zähler machen. korrigiere mich, wenn ich falsch liege.

4
surendra ben

Nein, Sie müssen Ihren eigenen Zähler erstellen. Noch ein weiteres Beispiel:

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

bei der Indizierung verwendet

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

Und natürlich können Sie local $index; anstelle von my $index; und so und so verwenden.

EDIT: Entsprechend dem Kommentar des ersten Jahres aktualisiert.

autobox::Core bietet neben vielen anderen Dingen eine praktische for-Methode:

use autobox::Core;

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

Alternativ sehen Sie sich ein Iterator-Modul an, zum Beispiel: Array::Iterator

use Array::Iterator;

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

Siehe auch:

/ I3az /

2
draegtun

Nun gibt es diesen Weg: 

use List::Rubyish;

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

siehe Liste :: Rubyish

1
Axeman

Oh ja das kannst du! (irgendwie, aber du solltest nicht). each(@array) im skalaren Kontext gibt Ihnen den aktuellen Index des Arrays.

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

Hier befindet sich each(@a) in einem skalaren Kontext und gibt nur den Index zurück, nicht den Wert an diesem Index. Da wir uns in einer for-Schleife befinden, haben wir den Wert bereits in $ _. Der gleiche Mechanismus wird häufig in einer While-Each-Schleife verwendet. Gleiches Problem.

Das Problem tritt auf, wenn Sie for(@a) erneut ausführen, der Index nicht wie erwartet auf 0 zurückgesetzt ist, sondern undef gefolgt von 0,1,2 ... einem Countdown. Die Perldoc von each() sagt, um dieses Problem zu vermeiden, verwenden Sie eine for -Schleife, um den Index zu verfolgen. https://perldoc.Perl.org/functions/each.html

Grundsätzlich gilt:

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

Ich bin ein Fan der alternativen Methode:

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

Ich habe es gerne versucht ....

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

zusamenfassend..

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

Beachten Sie bitte: 

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

Sie sollten den Index in den meisten Fällen nicht kennen müssen, Sie können dies tun

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

In diesem Fall wäre die Ausgabe 2, 3, 4 , da foreach einen Alias ​​auf das eigentliche Element setzt, nicht nur eine Kopie.

0