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

Shifting of 2D array slices

by Ryuchi (Initiate)
on Dec 06, 2008 at 23:14 UTC ( [id://728613]=perlquestion: print w/replies, xml ) Need Help??

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

I have a problem. I believe I have an array, @bigarray, like this:
[ ['123*jeff','tortoise','qwerty'] ['456*john','parrot','azerty'] ['789*jane','budgie','abcdef'] ]
I want to iterate over this to convert each row to:
['123','jeff','tortoise','qwerty']
Since I don't know how much additional data there is at the end*, I want to shift the data off, then unshift it back on. However, I am having great difficulty with shift; it doesn't seem to want to work. The splitting of the string is trivial; it's the shift/unshift which is being sticky.
my @row = $bigarray[$count]; print "dumper1:".Dumper(@row); my $item = shift @row; print "dumper2:".Dumper($item);
returns:
dumper1:$VAR1 = [ '<a href="http://www.wizards.com/default.asp?x=dnd/comp/mess +age" title="Click to Subscribe" >Berronar\'s Salve</a>', 'Heroic', '<em>Forgotten Realms Player\'s Guide</em>' ]; dumper2:$VAR1 = [ '<a href="http://www.wizards.com/default.asp?x=dnd/comp/mess +age" title="Click to Subscribe" >Berronar\'s Salve</a>', 'Heroic', '<em>Forgotten Realms Player\'s Guide</em>' ];
* Actually, I do, it varies.

Replies are listed 'Best First'.
Re: Shifting of 2D array slices
by jwkrahn (Abbot) on Dec 06, 2008 at 23:27 UTC

    It looks like you want something like this:

    $ perl -le' use Data::Dumper; my @bigarray = ( [ "123*jeff", "tortoise", "qwerty" ], [ "456*john", "parrot", "azerty" ], [ "789*jane", "budgie", "abcdef" ], ); print Dumper \@bigarray; @bigarray = map [ map split( /\*/ ), @$_ ], @bigarray; print Dumper \@bigarray; ' $VAR1 = [ [ '123*jeff', 'tortoise', 'qwerty' ], [ '456*john', 'parrot', 'azerty' ], [ '789*jane', 'budgie', 'abcdef' ] ]; $VAR1 = [ [ '123', 'jeff', 'tortoise', 'qwerty' ], [ '456', 'john', 'parrot', 'azerty' ], [ '789', 'jane', 'budgie', 'abcdef' ] ];
      @bigarray = map [ map split( /\*/ ), @$_ ], @bigarray;
      The second map is not neccessary. The return value of map can be a list, so
      @bigarray = map [ split /\*/ ], @bigarray;
      will do fine, too.


      holli, /regexed monk/

        split, by default, operates on $_, but the elements of @bigarray are references. You need to explicitly dereference them and then split the elements. That's why the internal map is necessary. Your suggestion leaves @bigarray looking this way:

        $VAR1 = [ [ 'ARRAY(0x504290)' ], [ 'ARRAY(0x531f00)' ], [ 'ARRAY(0x531e60)' ] ];
      @bigarray = map [ map split( /\*/ ), @$_ ], @bigarray;
      The second map statement (map split(/\*/), @$_) in the reply of jwkrahn is not necessary. In addition, it has the side effect of splitting all elements (strings) of the referenced array even though the intent seems to be to split only the first. None of the other elements contains the particular split pattern being used, so the extraneous splits have no effect; however, this approach depends on the assumption that the split pattern never appears in the other elements, and no one knows what the future may hold.

      (Note that the test data in @bigarray are slightly different.)

      >perl -wMstrict -le "use Data::Dumper; my @bigarray = ( [ '123*jeff', 'tortoise', 'qwe*rty', ], [ '456*john', 'parrot', 'aze*rty', ], [ '789*jane', 'budgie', 'abc*def', ], ); @bigarray = map [ map split(/\*/), @$_ ], @bigarray ; print Dumper \@bigarray; " $VAR1 = [ [ '123', 'jeff', 'tortoise', 'qwe', 'rty' ], [ '456', 'john', 'parrot', 'aze', 'rty' ], [ '789', 'jane', 'budgie', 'abc', 'def' ] ]; >perl -wMstrict -le "use Data::Dumper; my @bigarray = ( [ '123*jeff', 'tortoise', 'qwe*rty', ], [ '456*john', 'parrot', 'aze*rty', ], [ '789*jane', 'budgie', 'abc*def', ], ); @bigarray = map [ split(/\*/, $_->[0]), @$_[ 1 .. $#$_ ] ], @bigarray ; print Dumper \@bigarray; " $VAR1 = [ [ '123', 'jeff', 'tortoise', 'qwe*rty' ], [ '456', 'john', 'parrot', 'aze*rty' ], [ '789', 'jane', 'budgie', 'abc*def' ] ];
      Actually, I would prefer an approach using a for loop such as that of davidrw. In particular, the approach using splice can easily be modified to split any arbitrary element; this can also be done with the map approach, but with less concision.
Re: Shifting of 2D array slices
by moritz (Cardinal) on Dec 06, 2008 at 23:22 UTC
    You seem to confuse arrays with references to arrays (short arrayrefs). Reading perlreftut, perllol (lists of lists) and perldsc should clear up things.

    For example:

    my @row = $bigarray[$count];

    doesn't do what you want. Since $bigarry[$count] returns an arrayref, @row will contain only one value (that is, the reference). You'll probably want this instead:

    my @row = @{$bigarray[$count]};
Re: Shifting of 2D array slices
by davidrw (Prior) on Dec 07, 2008 at 01:22 UTC
    Besides the map solutions already posted, here's two others:
    setup for both:
    use Data::Dumper; my @bigarray = ( [ "123*jeff", "tortoise", "qwerty" ], [ "456*john", "parrot", "azerty" ], [ "789*jane", "budgie", "abcdef" ], ); print Dumper \@bigarray; # before ... print Dumper \@bigarray; # after
    • Using splice:
      splice @$_, 0, 1, split /\*/, $_->[0] for @bigarray;
    • Using shift and unshift:
      foreach my $arr ( @bigarray ){ my $item = shift @$arr; unshift @$arr, split /\*/, $item; }

Log In?
Username:
Password:

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

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

      No recent polls found