How to use string as two dimensional array

T

toplicanac

How to use string as two dimensional array

e.g.:
I have string

$string="123456abc";
-------------------------------------------
I want to read it like this

$mat(1,1) = "1"
$mat(2,1) = "2"
$mat(3,1) = "3"
$mat(1,2) = "4"
$mat(2,2) = "5"
$mat(3,2) = "6"
$mat(3,1) = "a"
$mat(3,2) = "b"
$mat(3,3) = "c"

But array can be 5x5, 10x10, or biger size.
What is easiest way to do it in Perl?
 
G

Gunnar Hjalmarsson

toplicanac said:
How to use string as two dimensional array

e.g.:
I have string

$string="123456abc";
-------------------------------------------
I want to read it like this

$mat(1,1) = "1"
$mat(2,1) = "2"
$mat(3,1) = "3"
$mat(1,2) = "4"
$mat(2,2) = "5"
$mat(3,2) = "6"
$mat(3,1) = "a"
$mat(3,2) = "b"
$mat(3,3) = "c"

Which programming language is that?
But array can be 5x5, 10x10, or biger size.
What is easiest way to do it in Perl?

Which ways have you considered?

Please study the posting guidelines for this group:
http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
 
J

John W. Krahn

toplicanac said:
How to use string as two dimensional array

e.g.:
I have string

$string="123456abc";
-------------------------------------------
I want to read it like this

$mat(1,1) = "1"
$mat(2,1) = "2"
$mat(3,1) = "3"
$mat(1,2) = "4"
$mat(2,2) = "5"
$mat(3,2) = "6"
$mat(3,1) = "a"
$mat(3,2) = "b"
$mat(3,3) = "c"

$ perl -le'
my $string = q!123456abc!;
print for
map substr( $string, ($_->[1] - 1) * 3 + ($_->[0] - 1), 1 ),
[1,1],[2,1],[3,1],[1,2],[2,2],[3,2],[1,3],[2,3],[3,3];
'
1
2
3
4
5
6
a
b
c


John
 
T

Tad McClellan

toplicanac said:
How to use string as two dimensional array


You cannot use a string as a two dimensional array.

You can however load a 2-D array from a string.

$string="123456abc";
-------------------------------------------
I want to read it like this

$mat(1,1) = "1"
$mat(2,1) = "2"
$mat(3,1) = "3"


x varies, y is constant. (and indexes start at zero in Perl)

$mat(1,2) = "4"
$mat(2,2) = "5"
$mat(3,2) = "6"


x varies, y is constant.

$mat(3,1) = "a"
$mat(3,2) = "b"
$mat(3,3) = "c"


x is constant, y varies!

Please exercise more care in describing what you want.

What is easiest way to do it in Perl?


This should get you started:

---------------------
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;

my $string = '123456abc';
my @twoD = str2array(3, $string);
print Dumper \@twoD;


sub str2array {
my($dim, $str) = @_;

die "'$str' is not evenly divisible by $dim\n"
if length($str) % $dim;

my @ra;
while ( my $row = substr $str, 0, 3, '' ) {
push @ra, [ split //, $row ];
}
return @ra;
}
---------------------


See also:

perldoc perlreftut
perldoc perlref
perldoc perllol
perldoc perldsc
 
S

samwyse

Anno said:
As an alternative to substr, the string could be decomposed with
unpack. That returns the list of all fragments at once, so the
while loop that builds the array can be replaced by map.

sub str2array {
my($dim, $str) = @_;

die "'$str' is not evenly divisible by $dim\n"
if length($str) % $dim;

return map [ split //], unpack "(a$dim)*", $str;
}

Since we're at it, unpack can do split's job too:

return map [ unpack '(a)*', $_], unpack "(a$dim)*", $str;

This has also turned Tad's clear code into an unreadable one-line
concoction. I like to point out pack/unpack alternatives occasionally,
but I don't mean to recommend them unequivocally. Pack/unpack sends
everyone on a trip to the docs, so their use must be justified by
substantial advantages, benchmarkable or otherwise.

But your first example has a lower score in golf, so I expect that most
people would stop there. So, does "split //" run slower than "unpack
'(a)*', $_" when used on 'a' x 1_000_000?

Benchmark: running split, unpack for at least 3 CPU seconds...
split: 3 wallclock secs ( 3.05 usr + 0.00 sys = 3.05 CPU) @
718665.25/s (n=2191929)
unpack: 1 wallclock secs ( 3.00 usr + 0.00 sys = 3.00 CPU) @
735399.67/s (n=2206199)
Rate split unpack
split 718665/s -- -2%
unpack 735400/s 2% --

Looks like unpack is marginally faster on my AIX server, but I doubt
that it would be noticable to the user.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,190
Latest member
ClayE7480

Latest Threads

Top