16

I have a array like this:

my @arr = ("Field3","Field1","Field2","Field5","Field4");

Now i use map like below , where /DOSOMETHING/ is the answer am seeking.

my %hash = map {$_ => **/DOSOMETHING/** } @arr

Now I require the hash to look like below:

Field3 => 0
Field1 => 1
Field2 => 2
Field5 => 3
Field4 => 4

Any help?

Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
Gopal SA
  • 949
  • 2
  • 17
  • 36

5 Answers5

26
%hash = map { $arr[$_] => $_ } 0..$#arr;

print Dumper(\%hash)
$VAR1 = {
          'Field4' => 4,
          'Field2' => 2,
          'Field5' => 3,
          'Field1' => 1,
          'Field3' => 0
        };
unbeli
  • 29,501
  • 5
  • 55
  • 57
19
my %hash;
@hash{@arr} = 0..$#arr;
Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
  • 3
    It's a shame `%hash` has to be pre-declared, so we can't write something like `my @hash{@arr} = 0 .. $#arr;`... – Zaid Jun 02 '10 at 13:38
  • 4
    @Zaid There are always cute tricks such as `@$_{@arr} = 0 .. $#arr for \my %hash;`, but eugene's code has less shock value. – Greg Bacon Jun 02 '10 at 13:47
  • @gbacon : Agreed, one shouldn't sacrifice readability for one-line-cramming. It's just that I would've imagined that Perl could auto-vivify with array slices as well. – Zaid Jun 02 '10 at 13:53
  • @Zaid Your proposed syntax would be nice. You should send a patch to p5p! – Greg Bacon Jun 02 '10 at 14:06
2

In Perl 5.12 and later you can use each on an array to iterate over its index/value pairs:

use 5.012;

my %hash;

while(my ($index, $value) = each @arr) {
    $hash{$value} = $index;
}
Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
2

Here's one more way I can think of to accomplish this:

sub get_bumper {
    my $i = 0;
    sub { $i++ };
}

my $bump = get_bumper;         # $bump is a closure with its very own counter
map { $_ => $bump->(); } @arr;

As with many things that you can do in Perl: Don't do this. :) If the sequence of values you need to assign is more complex (e.g. 0, 1, 4, 9, 16... or a sequence of random numbers, or numbers read from a pipe), it's easy to adapt this approach to it, but it's generally even easier to just use unbeli's approach. The only advantage of this method is that it gives you a nice clean way to provide and consume arbitrary lazy sequences of numbers: a function that needs a caller-specified sequence of numbers can just take a coderef as a parameter, and call it repeatedly to get the numbers.

Community
  • 1
  • 1
j_random_hacker
  • 50,331
  • 10
  • 105
  • 169
1

A very old question, but i had the same problem and this is my solution:

use feature ':5.10';

my @arr = ("Field3","Field1","Field2","Field5","Field4");
my %hash = map {state $i = 0; $_ => $i++} @arr;
KlausR
  • 27
  • 3