http://qs321.pair.com?node_id=685083

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

I have a need to convert this string into a two dimensional array.

For instance, I need to convert this:

0 X X X X X X X X 1 X X X X X X X X 2 X X X X X X X X 3 X X X X X X X X 4 X X X X X X X X 5 X X X X X X X X 6 X X X X X X X X 7

Into this:

0 X X X X X X X
X 1 X X X X X X
X X 2 X X X X X
X X X 3 X X X X
X X X X 4 X X X
X X X X X 5 X X
X X X X X X 6 X
X X X X X X X 7

In the above instance this happens to be @array 8 x 8 in size, but sometimes it can be more or less. I will be feeding x values (columns) into one for split points and y values into how many rows the array has.

Regards, Tom

Replies are listed 'Best First'.
Re: String to two dimensional array
by BrowserUk (Patriarch) on May 06, 2008 at 22:46 UTC

    sub string2matrix { my( $x, $y, $s ) = @_; die "Can't create $x x $y matrix from string length: ", length $s unless length( $s ) == $x * 2 * $y -1; return map{ map{ [ split ] } $_ } unpack "(A@{[ $x * 2 ]})*", $s; } my $s = '0 X X X X X X X X 1 X X X X X X X X 2 X X X X X X X X 3 X X X + X X X X X 4 X X X X X X X X 5 X X X X X X X X 6 X X X X X X X X 7';; my @a = string2matrix( 8, 8, $s );; pp \@a;; [ [0, "X", "X", "X", "X", "X", "X", "X"], ["X", 1, "X", "X", "X", "X", "X", "X"], ["X", "X", 2, "X", "X", "X", "X", "X"], ["X", "X", "X", 3, "X", "X", "X", "X"], ["X", "X", "X", "X", 4, "X", "X", "X"], ["X", "X", "X", "X", "X", 5, "X", "X"], ["X", "X", "X", "X", "X", "X", 6, "X"], ["X", "X", "X", "X", "X", "X", "X", 7], ]

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      Thank you so much for your help. I am new to the perlmonks site, but it looks like a great place to learn perl.

      Anyway, I understand most of what you did except for the line that says:

      pp \@a;;
Re: String to two dimensional array
by pc88mxer (Vicar) on May 06, 2008 at 23:40 UTC
    Here's another approach that you might find instructive:
    my $text = "0 X X X ..."; my @items = split(' ', $text); my @array; while (@items) { push(@array, [ splice(@items, 0, 8) ]); } pp \@array; use Data::Dumper;
    The basic idea is:
    1. Split the input string into an array (@items).
    2. Remove the first 8 elements of @items, create an array ref out of those elements, and push that array ref onto the end of @array
    3. Repeat step 2 until @items is empty.

    To make sure you have a full matrix, you can check the length of the last row with:

    die "incomplete last row\n" unless (scalar(@{$array[-1]} == 8);
Re: String to two dimensional array
by GrandFather (Saint) on May 07, 2008 at 03:02 UTC

    TIMTOWTDI:

    use strict; use warnings; my $str = '0 X X X X X X X X 1 X X X X X X X X 2 X X X X X X X X 3 X X + X X X X X X 4 X X X X X X X X 5 X X X X X X X X 6 X X X X X X X X 7' +; my @array = map {[split]} $str =~ /(.{16})/g; print "@$_\n" for @array;

    Prints:

    0 X X X X X X X X 1 X X X X X X X X 2 X X X X X X X X 3 X X X X X X X X 4 X X X X X X X X 5 X X X X X X X X 6 X

    Perl is environmentally friendly - it saves trees
Re: String to two dimensional array
by kyle (Abbot) on May 07, 2008 at 02:37 UTC

    I like pc88mxer's solution better than my own, but in the interest in showing different ways of doing the same thing, I'll post it anyway.

    use Data::Dumper; my $in = '0 X X X X X X X' . ' X 1 X X X X X X' . ' X X 2 X X X X X' . ' X X X 3 X X X X' . ' X X X X 4 X X X' . ' X X X X X 5 X X' . ' X X X X X X 6 X' . ' X X X X X X X 7'; print Dumper [ string2matrix( $in, 8 ) ]; sub string2matrix { my ( $string, $width ) = @_; my @out; while ( $string ) { my @iter = split /\s+/, $string, $width + 1; $string = scalar @iter > $width ? pop @iter : ''; push @out, \@iter; } return @out; }
Re: String to two dimensional array
by plobsing (Friar) on May 07, 2008 at 08:13 UTC
    Just for fun, a solution using PDL:
    use strict; use warnings; use PDL; use PDL::Char; my $str = "0 X X X X X X X X 1 X X X X X X X X 2 X X X X X X X X 3 X X + X X X X X X 4 X X X X X X X X 5 X X X X X X X X 6 X X X X X X X X 7" +; print pp_matrix( str2matrix($str, 8, 8) ); sub str2matrix { # my ($str, $x, $y) = @_; PDL::Char->new( shift ) ->mslice([0,-1,2]) ->reshape(1, shift, shift); } sub pp_matrix { # my ($matrix) = @_; shift ->reshape(-1) ->append( PDL::Char->new("\n") ) ->flat ->atstr(0); }
Re: String to two dimensional array
by jdporter (Paladin) on May 07, 2008 at 12:47 UTC

    Yet another way, using List::MoreUtils:

    use List::MoreUtils qw( natatime ); $_ = '0 X X X X X X X X 1 X X X X X X X X 2 X X X X X X X X 3 X X X X +X X X X 4 X X X X X X X X 5 X X X X X X X X 6 X X X X X X X X 7'; my @a = split; my $it = natatime(8,@a); while (my @v = $it->()) { print "@v\n"; }

    Converting that into an appropriately parameterized function is an exercise left for... you. ;-)

    A word spoken in Mind will reach its own level, in the objective world, by its own weight
Re: String to two dimensional array
by tashworth (Initiate) on May 07, 2008 at 14:02 UTC

    Wow you guys are awesome. Even though I am Perl novice, I have added this site to my favorites and hopefully one day I can contribute as much as you guys do. This is an awesome community.

    Regards, Tom