автоматически получить индекс цикла в цикле foreach в perl



если у меня есть следующий массив в Perl:



@x = qw(a b c);


и я повторяю его с foreach, потом $_ будет ссылаться на текущий элемент в массиве:



foreach (@x) {
print;
}


выведет:



abc


есть ли аналогичный способ получить индекс текущего элемента, без ручного обновления счетчика? Что-то вроде:



foreach (@x) {
print $index;
}


здесь $index обновляется как $_ выход вывод:



012
577   12  

12 ответов:

Как сказал codehead, вам придется перебирать индексы массива вместо его элементов. Я предпочитаю этот вариант и C-стиль петли:

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

в Perl до 5.10, вы можете сказать

#!/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 чтобы объявить переменную, которая никогда не будет повторно инициализирована (в отличие от тех, которые создаются с помощью мой). Это позволяет сохранить $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.

это не поможет вам сейчас, но в 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"
}

The Z оператор сжимает два списка вместе (т. е. он берет один элемент из первого списка, затем один элемент из второго, затем один элемент из первого и так далее). Второй список-это лень список, содержащий любое число от 0 до бесконечности (по крайней мере, теоретически). Элемент -> $elem, $index говорит, что мы берем два значения одновременно из результата zip. Остальное должно выглядеть нормально для вас (если вы не знакомы с say

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

и конечно, вы можете использовать local $index; вместо my $index; и так и так.

EDIT: Обновлено в соответствии с комментарием первого ysth.

да. Я проверил так много книг и других блогов... вывод: для счетчика циклов нет системной переменной. мы должны сделать свой собственный счетчик. поправьте меня, если я ошибаюсь.

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/

Ну есть так:

use List::Rubyish;

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

посмотреть Список::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 /a b c d/;
my $count;
for (@array) { print "\n",$count++," $_"; }
undef $count;

Пожалуйста, обратите внимание:

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

Comments

    Ничего не найдено.