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

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

Let's assume I have a matrix (any sort of n-dimensional array) @m. Better yet, let's pretend it's in an object, so to access it we have to do \$o->{m}. Now let's assume I have a dictionary (hash) that assigns names to certain elements in that matrix, which are represented by an anonymous array of coordinates:

```   %h = (
a => [3, 9, 4],
b => [2, 1, 3],
c => [9, 7, 2],
...
)
Is there any way to represent the element in the matrix using coordinates from the hash (let's also pretend that we're using a variable as the hash key) that is more elegant than \$o->{m}[\$h{\$key}->][\$h{\$key}->][\$h{\$key}->]? All those brackets are giving me a headache.

The only alternative I could think of was:

```    my (\$x,\$y,\$z) = @{\$h{\$key}};
\$o->{m}[\$x][\$y][\$z] = ...
but making three new scalars to clarify a single operation (let's assume that there will only be a single lookup within this scope) seems a little excessive, and if you count the newline it uses the same exact amount of keystrokes. If this is something that I need to do in more than one place, then it would make sense to make something like:
```    sub matrixGet {
my (\$o, \$x, \$y, \$z) = @_;
return \$o->{m}[\$x][\$y][\$z];
}
sub matrixSet {
my (\$o, \$x, \$y, \$z, \$val) = @_;
\$o->{m}[\$x][\$y][\$z] = \$val;
}
...
\$o->matrixGet(@{\$h{\$key}});
\$o->matrixSet(@{\$h{\$key}},5);
or to be more flexible:
```    sub matrixGet {
my (\$m, \$x, \$y, \$z) = @_;
return \$m->[\$x][\$y][\$z];
}
...
matrixGet(\$o->{m},@{\$h{\$key}});
but now this looks so cumbersome. And what if I have matrices of different dimensions? Now I need matrixGet2D and matrixGet3D and matrixGet4D, etc. And all I really wanted to do was access a certain element using a set of coordinates stored somewhere else for a (relatively) tiny little script I'm writing to manage some data to assist me in a minigame within a game I'm playing. It's already growing to double or triple the size I thought it would originally. But I digress. Is there a simple inline method for using an arrayref as the indexes of a matrix?

And if there's any other blatantly unnecessary step in my code please let me know. It's been a while since I used Perl and mucking about in references was never my strong suit.

Thank you.

\$,=qq.\n.;print q.\/\/____\/.,q./\ \ / / \\.,q.    /_/__.,q..
Happy, sober, smart: pick two.

Replies are listed 'Best First'.
Re: Accessing a matrix value from a dictionary of named coordinate tuples
by kcott (Bishop) on Mar 11, 2014 at 22:40 UTC

G'day xyzzy,

I think this might be the type of thing you're after.

```#!/usr/bin/env perl -l

use strict;
use warnings;

my @matrix = (
[qw{A B C}],
[qw{D E F}],
[qw{G H I}],
[qw{J K L},
[
[qw{M N O P Q}, [qw{R S T}], qw{U V W X Y Z}]
]
],
);
my %dict = (
a => [0, 0],
b => [0, 1],
e => [1, 1],
g => [2, 0],
i => [2, 2],
p => [3, 3, 0, 3],
s => [3, 3, 0, 5, 1],
);

for (qw{a b e g i p s}) {
print "\$_ => ", get_element(\@matrix, \$dict{\$_});
}

sub get_element {
my (\$matrix, \$coords) = @_;

my \$element = \$matrix->[shift @\$coords];
@\$coords ? get_element(\$element, \$coords) : \$element;
}

Output:

```a => A
b => B
e => E
g => G
i => I
p => P
s => S