in reply to One Dimensional Array into Two

$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

Replies are listed 'Best First'.
Re^2: One Dimensional Array into Two
by gone2015 (Deacon) on Aug 22, 2008 at 14:43 UTC
    $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.

        My ambiguity was probably due to the fact that I wasn't aware that there were multiple ways to do this. I guess it's Perl that we are talking about, so I should have assumed that there are always multiple ways of doing any particular thing. However, this discussion has really helped me clarify this usage. Thank you for your comments and time. Joe

        Well... yes. I admit it.

        From the original question I had made an obviously irrational assumption. I had assumed that the application was reading lines (presumably from a file), splitting those into columns (@column = split /\s+/, $line ;) and storing the result in a two-dimensional array of cells (@sheets). That assumption lead me astray, and I slipped into the unwise contemplation of what I now acknowledge to be a heresy.

        I freely confess my sins and repent.

        I accept, without reservation, that on occasion it may be desirable to have one (or more) rows in a two-dimensional array which are accessible by an alias, say, @columns. And I would like now to apologize, humbly and deeply, if my remarks suggested otherwise, in any way, whatsoever.

        I feel foolish now, and would like uncountably many other offences of hubris to be taken into consideration.

        In mitigation, however, I would like to draw attention to the very first words of my remarks: "As a general proposition".

        And I suggest that, in general, $sheets[1] = \@column; won't be a deliberate exercise in aliasing, but will be a potential hazard, which could bite the innocent programmer in their unsuspecting gluteus maximus (or glutinous maximus, in some cases).

        I now undertake to collect my hair shirt from the cleaners at the earliest opportunity, and wear it more often to remind me to transgress no more.

      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.