简体   繁体   中英

What's the Perl equivalent of Python's enumerate?

I'm looking for a function in Perl 5 that works similarly to Python's enumerate built-in. It would return a list of references to arrays, where each array is [$index, $element] :

@a = ("a", "b", "c");
@b = enumerate @a;
# @b = ([0, "a"], [1, "b"], [2, "c"])

List::Util and List::MoreUtils don't seem to have this function. Is there another module that does?

You can use map , like this

my @data = qw / a b c /;
my @enumeration = map [ $_, $data[$_] ], 0 .. $#data;

Perl doesn't have a built-in function to do that but it's easy to roll your own.

Using map :

my @a = qw(a b c);
my $i = 0;
my @b = map [$i++, $_], @a; # ([0, 'a'], [1, 'b'], [2, 'c'])

As of v5.20, Perl's new slice syntax does something similar:

my @a = qw(a b c);
my @b = %a[0..$#a]; # (0, 'a', 1, 'b', 2, 'c')

That slice syntax returns a list of index/value pairs but it's a flat list. The pairs aren't grouped into nested arrays. If that's important to your application you can use the pairmap function from List::Util to do it:

use List::Util qw(pairmap);
my @a = qw(a b c);
my @b = pairmap {[$a, $b]} %a[0..$#a]; # ([0, 'a'], [1, 'b'], [2, 'c'])

enumerate returns an iterator, not a list, so you should really be asking for an iterator.


In Perl 5.12.0 and up, you can use each to iterate over arrays:

use strict;
use warnings 'all';
use 5.012;

my @a = qw(foo bar baz);

while (my ($i, $v) = each @a) {
    say "$i -> $v";
}

__END__
0 -> foo
1 -> bar
2 -> baz

However, you should be very careful when using each ; some people even discourage its use altogether .

Use the List::Enumerate module.

use List::Enumerate qw(enumerate);
@a = ("a", "b", "c");
@b = map { [ $_->index, $_->item ] } enumerate(@a);
sub enumerate(&@) {
    local *f = shift;
    my @array = @_;
    my @ret;
    my $pkg = caller;
    for ( my $i = 0 ; $i < @array ; $i++ ) {
        no strict 'refs';
        local *{ $pkg . '::a' } = \$i;
        local *{ $pkg . '::b' } = \$array[$i];
        push @ret, f( $i, $array[$i] );
    }
    @ret;
}
my @tmp = enumerate { ($a, $b) } 'a'..'z';
say "@tmp";

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM