Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to use a hash of arrays, but there's a few things that I'm not sure about. First, are these both correct ways of setting an array in the hash?

$hash{$id} = (1,2,3);

my @temp = (1,2,3); $hash{$id} = @temp;


Now, when accessing a value in an array in a hash, is this correct:

@{$hash{$id}}[0]

Or is this:

${$hash{$id}}[0]

Thanks.

Replies are listed 'Best First'.
Re: Regarding Hashes of Arrays
by chromatic (Archbishop) on Aug 10, 2004 at 19:56 UTC

    The answer to your first question is no. Neither is correct. Hash values can only be scalars. If you want to store multiple values, you need to store a reference (see References Quick Reference) to another data structure.

    As for your second question, both will work. The first works best when you're accessing an array slice -- multiple elements at once -- or when you want to evaluate that part of the expression in list context. The second is more useful most of the time, especially if you don't yet know about slices or why you'd want to do it.

    I'd prefer this syntax for accessing a single element though:

    $hash{$id}[0]
Re: Regarding Hashes of Arrays
by Joost (Canon) on Aug 10, 2004 at 19:59 UTC
    They're both incorrect. If you'd use warnings you'd get a warning from the first construct.

    $hash{$id} = (1,2,3); will set $hash{$id} = 3 (the last element in the list).

    and $hash{$id} = @temp; will set $hash{$id} = 3 (the length of @temp).

    You cannot literally make a hash with arrays as the values in Perl, you need array-references:

    $hash{$id} = [1,2,3]; # [ ... ] creates an anonymous array ref @temp = (1,2,3); $hash{$id} = \@temp; # \ makes an explicit reference to @temp
    Note that \(1,2,3) will make a list of references to 1, 2 and 3, so don't use that.

    If you want to read one of the values from the array ref you do:

    $x = ${$hash{$id}}[0]; # or $x = $hash{$id}[0]; # or $x = $hash{$id}->[0];

    I like the last syntax best, because it makes it clear that there is a reference (more or less equivalent to a "pointer" in C speak) involved.

    If you want to whole list of values from the array, you can do:

    my @values = @{$hash{$id}};
    perlref has a lot of info about this.

      I like the last syntax best, because it makes it clear that there is a reference (more or less equivalent to a "pointer" in C speak) involved.

      The fact that there is a multi-dimentional datastructure should already make it assumed there are references involved. Or do you know of a way to do complex datastructures in Perl without references?

      "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

Re: Regarding Hashes of Arrays
by duff (Parson) on Aug 10, 2004 at 19:59 UTC

    Nope! What you want are these:

    $hash{$key} = [ 1,2,3 ]; # Note the square brackets $hash{$otherkey} = [ @temp ]; # same same $hash{$key2} = \@temp;

    The first two create a reference to an anonymous array that has a copy of the contents. The last one creates a reference to an existing array.

    And to access them, it's just ...

    $hash{$key}[0]

    See perlreftut, perldsc, perlref, and perllol for more information

Re: Regarding Hashes of Arrays
by johnnywang (Priest) on Aug 10, 2004 at 19:55 UTC
    You probably want hashes of references of arrays rather than arrays themselves. I'm not sure you can do hashs of arrays directly. But the following will work for you.
    $hash{$id} = [1,2,3]; my @temp = (1,2,3); $hash{$id} = \@temp;
    You can then access them as
    @{$hash{$id}}; # for the whole array $hash{$id}->[0]; # for the first element
Re: Regarding Hashes of Arrays
by hardburn (Abbot) on Aug 10, 2004 at 19:58 UTC

    Perl's complex data structures are all based on references. In fact, an awful lot of more advanced Perl topics involve references. So I suggest getting a solid grasp of references first.

    "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.