Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Getting an Array Reference Into an Array

by qazwart (Scribe)
on Jun 07, 2006 at 19:34 UTC ( [id://554126]=perlquestion: print w/replies, xml ) Need Help??

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

I have to produce code that is readable and easy to follow for our support group. Sometimes I have a slighly complex datastructure like this:

$myHash{"uno"} = "one"; $myHash{"dos"} = "two"; $myHash{"tres"}->[0] = "three-point-oh"; $myHash{"tres"}->[1] = "three-point-one"; $myHash{"tres"}->[2] = "three-point-two"; $myHash{"quatro"} = "four";
I want to manipulate the array in $myHash{"tres"}, and in order to prevent deferencing it all the time, I'll copy it into an actual array:
@myArray = @{$myHash{"tres"}}; #DeRef & Copy to @myArray $myArray[3] = "three-point-three"; $myArray[4] = "three-point-four";
Once I'm done manipulating the data, I want to put it back into the original data structure. I can do either one of these:
@{$myHash{"tres"}} = @myArray; #Copies Array to Hash $myHash{"tres"} = \@myArray; #Copies Ref to Hash
For very large arrays, the second statement is faster than the first one.

Of course, the problem is my initial copy to @myArray is not very efficient either. What I'd really love to do is something like this:

\@myArray = $myHash{"tres"};
Which would allow me to refer to $myHash{"tres"} as @myArray in my code without copying the whole array in the first place. (Then, I wouldn't even worry about putting the array back into my original data structure).

I guess what I'm really interested in is creating an alias of $myHash{"tres"} as @myArray. Is there anyway to do that in Perl?

Replies are listed 'Best First'.
Re: Getting an Array Reference Into an Array
by Joost (Canon) on Jun 07, 2006 at 19:51 UTC
    Fletch has already answered your question, but...
    I want to manipulate the array in $myHash{"tres"}, and in order to prevent deferencing it all the time, I'll copy it into an actual array
    Personally, i prefer to just copy the reference.
    my $aref = $myHash{"tres"}; $aref->[0] = 'bla'; # etc.
    This also avoids copying the arrays. Dereferencing is a tiny bit slower than using an alias, but my guess is that it just won't be noticable, and using local() unless you really have to is just ugly IMO.

Re: Getting an Array Reference Into an Array
by Fletch (Bishop) on Jun 07, 2006 at 19:37 UTC

    You want to make a local alias.

    { local *myArray = $myHash{ "tres" }; $myArray[ 99 ] = "luftballons"; }

      Adding our @myArray allows the snippet to be used with use strict 'vars';.

      { our @myArray; local *myArray = $myHash{ "tres" }; $myArray[ 99 ] = "luftballons"; }
        Adding our @myArray allows the snippet to be used with use strict 'vars';.
        Yeah, I figured that I needed the our @myArray when I added the use strict; to the program.

        However, I tried the program with and without the local and it seems to work either way. Does the our @myArray remove the need for local? I've got the entire program below.

        use strict; use warnings; my %myHash; $myHash{"uno"} = "one"; $myHash{"dos"} = "two"; $myHash{"tres"}->[0] = "three-point-oh"; $myHash{"tres"}->[1] = "three-point-one"; $myHash{"tres"}->[2] = "three-point-two"; $myHash{"quatro"} = "four"; our @myArray; *myArray = $myHash{"tres"}; $myArray[3] = "three-point-three"; $myArray[4] = "three-point-four"; $myArray[5] = "three-point-five"; foreach my $key (keys(%myHash)) { if (ref($myHash{$key}) eq "ARRAY") { for (my $item = 0; $item <= $#{$myHash{$key}}; $item++) { print qq($key->).qq([$item] = "$myHash{$key}->[$item]"\n); } } else { print qq($key = "$myHash{$key}"\n); } }
Re: Getting an Array Reference Into an Array
by NetWallah (Canon) on Jun 07, 2006 at 19:57 UTC
    There are several other ways to achieve your objective - you could pass the array ref into a sub, and use a local alias to an arayref, as in
    sub HandleTres{ my $tresRef = shift; $tresref->[0]= "Something else"; }
    or, use a reference assignment in your mainline code:
    my $TresRef = $myHash{tres}; $TresRef->[1] = "Tres punto uno";

         "For every complex problem, there is a simple answer ... and it is wrong." --H.L. Mencken

Re: Getting an Array Reference Into an Array
by debiandude (Scribe) on Jun 07, 2006 at 19:51 UTC

    Why don't you do this:

    my @myArray = qw/three-point-oh three-point-one three-point-two/; $myHash{"tres"} = \@myArray; # then do everything onto @myArray; push @myArray, "three-point-three", "three-point-four"; # And $myHash is automatically updated print join(' ', @{$myHash{"tres"}}), "\n";

      Why don't you do this:
      my @myArray = qw/three-point-oh three-point-one three-point-two/; $myHash{"tres"} = \@myArray; # then do everything onto @myArray;
      Because in my actual program, I'm not creating the array from scratch. The whole datastructure is given to me, and I have to manipulate it and return it back to the calling program.

      In the actual program, it is an array of a hash of a hash, and the array itself could contain thousands of members. That's why I don't want to use dereferencing and that's why I didn't want to copy it.

      I posted a simple program to demonstrate that concept.

Re: Getting an Array Reference Into an Array
by qazwart (Scribe) on Jun 08, 2006 at 14:52 UTC
    Okay: Using the typeglob for myArray allows me to point @myArray to the same memory location as $myHash{"tres"}.

    This is probably the best solution because it allows me to treat the data in $myHash{"tres"} in such functions as join, split, and other array specific functions.

    Using our is needed for getting around the use strict Perl pragma. Wrapping up everything in a block and using local keeps the scope of my redefinition of @myArray to that area of the program. Otherwise, if I use @myArray again somewhere else in the program, I could be changing $myHash{"tres"} without meaning to.

    Thanks everybody for your help.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://554126]
Approved by Paladin
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (2)
As of 2024-04-20 03:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found