http://www.perlmonks.org?node_id=972111

Dr. Mu has asked for the wisdom of the Perl Monks concerning the following question:

I thought I understood hash arrays until I encountered this:
use strict; my @hashes = ({}) x 10; $hashes[$_]{$_} = 1 foreach (0 .. 9); foreach (0 .. 9) { print join(':', keys %{$hashes[$_]}), "\n" }
which prints:
6:3:7:9:2:8:1:4:0:5 6:3:7:9:2:8:1:4:0:5 6:3:7:9:2:8:1:4:0:5 6:3:7:9:2:8:1:4:0:5 6:3:7:9:2:8:1:4:0:5 6:3:7:9:2:8:1:4:0:5 6:3:7:9:2:8:1:4:0:5 6:3:7:9:2:8:1:4:0:5 6:3:7:9:2:8:1:4:0:5 6:3:7:9:2:8:1:4:0:5
What gives? I was expecting it to output:
0 1 2 3 4 5 6 7 8 9
('Using ActivePerl 5.8.4 on Win XP.)

Thanks,
-Phil

Edit: Oh nevermind. I know what the problem is: every element of the array contains a reference to the same hash. D'oh!

This fixes the problem:

my @hashes = map{{}} (0 .. 9);

-Phil

Replies are listed 'Best First'.
Re: Array of hashes misbehaving?
by Eliya (Vicar) on May 23, 2012 at 22:22 UTC
    This fixes the problem: ...

    Actually, in this particular case, you could also just not initialize the array, i.e. simply say

    my @hashes; $hashes[$_]{$_} = 1 foreach (0 .. 9);

    and let autovivification do the job.

      Good point. Thanks for the reminder!

      -Phil

Re: Array of hashes misbehaving?
by ikegami (Patriarch) on May 23, 2012 at 22:33 UTC

    If I were to use map, I wouldn't use

    my @hashes = map { {} } 0..9; $hashes[$_]{$_} = 1 for 0..9;

    I would use

    my @hashes = map { { $_ => 1 } } 0..9;
      In my minimalistic example, used to illustrate the problem I was having, that would certainly work. But in the real program which spurred my example, it would not.

      But thanks just the same!
      -Phil