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}->[0]][$h{$key}->[1]][$h{$key}->[2]]? 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

    I'll leave you to implement whatever OO framework you need.

    -- Ken

Re: Accessing a matrix value from a dictionary of named coordinate tuples
by Jim (Curate) on Mar 11, 2014 at 22:45 UTC

    Have you considered using an existing CPAN module to do the kind of stuff you're trying to do here with matrices? Might PDL (Perl Data Language) be useful to you? (See http://pdl.perl.org/.)

    Jim