Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

One Dimensional Array into Two

by JoeJaz (Monk)
on Aug 21, 2008 at 22:23 UTC ( [id://706013]=perlquestion: print w/replies, xml ) Need Help??

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

Hey all, I am a bit rusty with my Perl skills. I was wondering if there was an easy way to store an entire one-dimensional array into part of a two-dimensional array. For example:
 ...
 my @sheets; 
 my @column = split /(\s)+/, $line;
 @sheets1 = @column;
In this example, @column is the one-dimensional array and @sheets is the two-dimensional array. Howerver, this doesn't quite work the way I would expect. I don't want to have to resort to nested for loops if I can help it. Figured there should be some simple syntax for doing this. I'm having difficulty finding examples of this on Google. Any advice is much appreciated. Thanks for reading. Joe

Replies are listed 'Best First'.
Re: One Dimensional Array into Two
by moritz (Cardinal) on Aug 21, 2008 at 22:34 UTC
      Thank you for your help. It didn't even occur to me to use push.
Re: One Dimensional Array into Two
by gone2015 (Deacon) on Aug 21, 2008 at 22:36 UTC

    A "two dimensional array" is really a one dimensional array whose entries are ref:ARRAY, that is references to arrays.

    So you want something along the lines of:

    push @sheets, [split /\s+/, $line] ;
    which is using the anonymous array composer to generate each entry for the "two dimensional array".

    BTW, I wasn't sure whether you meant split /(\s)+/, which I believe will capture the whitespace separators as items in the resulting list ?

      ... and if /(\s)+/ is really meant, it is cleaner written as /\s*(\s)/, in which case it's obvious that only the last matched whitespace will actually be in $1.
      I as having a seperate issue with the whitespace. Your suggestion to remove the parens solved in perfectly. Also, the syntax for the push is very concise. Thank you for your help. Joe
Re: One Dimensional Array into Two
by FunkyMonk (Chancellor) on Aug 21, 2008 at 22:36 UTC
    $sheets[1] = \@column;

    Perhaps?

    No one can tell you for sure. They can only guess, just as I have.

    Can you some show us some data, and what you expect to happen with it?


    Unless I state otherwise, all my code runs with strict and warnings
      $sheets[1] = \@column;
      Perhaps?

      As a general proposition, I would worry about this construct -- in particular I would worry whether @column could be changed later, generating side effects in the @sheet array.

      However, the following works fine:

      my @sheet = () ; while ($line = <SHEET>) { my @columns = split /\s+/, $line ; push @sheet, \@columns ; } ;
      Nevertheless, alarm bells might be going off in the back of one's mind: this appears to be assigning a pointer to an "automatic" variable (eek!).

      It's OK though, you just have to remember that @columns is not really the name of the array, it's the name of a pointer to an array data structure on the heap; and, \@columns isn't returning the address of @columns, it's making a copy of the pointer. When @columns drops out of scope, it's copy of the pointer disappears, but the array data structure stays in the heap until all pointers to it disappear. Obvious, really :-)

      The paranoid might worry that @columns might have a life-time of the while loop -- so we'd have to worry about what the assignment does ! Though Perl is, at heart, an interpretted language, so my is an executable item, which might reinitialise @columns each time around the loop, before the assignment ?

      It would be easy to make this mistake:

      my (@sheet, @columns) ; while (my $line = <SHEET>) { @columns = split /\s+/, $line ; push @sheet, \@columns ; } ;
      which does leave @sheet with all entries pointing to the same thing: the last line of the input ! (From which we deduce that the assignment to @columns overwrites the array data structure that @columns implicitly points to. Which in some ways is a bit of a surprise ! We also deduce that in the previous case, my @columns within the while loop was reset before the assignment, or was discarded at the end of the loop each time around.)

      Anyway, the point here is: when constructing data structures you can use \@foo or \%bar, but in doing so you (a) have to be careful, and (b) have to know what it is you have to be careful about !

      push @sheet, [ @columns ] ;
      is unambiguous and secure -- but I guess requires a copy of the array data to be made. One hopes that:
      push @sheet, [ split /\s+/, $line ] ;
      is bright enough to spot that the list produced by split is already anonymous, so that the [...] needs only to return its address !

        As a general proposition, I would worry about this construct -- in particular I would worry whether @column could be changed later, generating side effects in the @sheet array.
        You seem to assume that isn't what the OP wanted. Sometimes that's exactly why \@columns must be used over [ @columns ].

        The OP was sufficiently vague that neither of us could have guessed at what they wanted.

        The syntax that creates the copy, @columns , was sufficient for what I need to do in this case (basically iterate through a text file and read each space delimited value into a multi-dimensional array). However, it's good to know that these array pointers can be controled so precicely. Never knew that you could assign a 2d array by value or by reference, so to speak. Thank you for making this distinction. I'll definately reference this post when I need to create it as a pointer. I appreciate the help.
Re: One Dimensional Array into Two
by llancet (Friar) on Aug 22, 2008 at 04:49 UTC
    I know two ways to achieve it. If you just want to store it, you may say:
    push @sheet,[@array];
    or
    $sheet[$n]=[@array];
    another way is to say:
    push @sheet,\@array;
    or
    $sheet[$n]=\@array;
    In the second way, when you change the values in @array, the corresponding value in @sheet will also be changed; but the first way wont.
      I like this break-down of the different ways to accomplish this. Thank you.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (8)
As of 2024-04-18 15:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found