Reputation: 442
Technically speaking there are no multi-dimensional arrays in Perl, but you can use single dimensional arrays in Perl to act as if they had more than one dimension.
In Perl each element of an array can be a reference to another array, but syntactically they would look like a two-dimensional array.
I want to convert 2-dimensional integer array into string in Perl. I have declared 2-dimensional integer array as follows:
my @array1=[[1,2,3],[1,2,3],[1,2,3]];
OR
my @array2=((1,2,3),(1,2,3),(1,2,3));
now I need to create a subroutine that will return string as "{{1,2,3},{1,2,3},{1,2,3}}"
. I have tried the following subroutine:
sub TwoDArrayOutputString {
my ($outputs)= @_;
my $finaloutput="{";
foreach my $output ($outputs) {
foreach my $out (@$output) {
$finaloutput.="{"."}";
#$finaloutput.="{".join(',',@output)."}";
}
$finaloutput.=",";
}
$finaloutput.="}";
return $finaloutput;
}
sub TwoDArrayOutputString1 {
my ($outputs)= @_;
if ( ref($outputs) eq "REF" ) {$outputs = ${$outputs};}
my $finaloutput="{";
foreach my $output ($outputs) {
foreach my $out (@$output) {
$finaloutput.="{"."}";
#$finaloutput.="{".join(',',@output)."}";
}
$finaloutput.=",";
}
$finaloutput.="}";
return $finaloutput;
}
sub TwoDArrayOutputString2{
my ($array)= @_;
my $finaloutput="{";
for my $row ( 0..$#array ) {
my @columns = @{ $array[$row] }; # Dereferencing my array reference
$finaloutput.="{";
for my $column ( @columns ) {
$finaloutput.=$column.",";
}
$finaloutput=substr($finaloutput,0,length($finaloutput)-1);
$finaloutput.="}".",";
}
$finaloutput=substr($finaloutput,0,length($finaloutput)-1);
$finaloutput.="}";
return $finaloutput;
}
print TwoDArrayOutputString(@array1)."\n";
print TwoDArrayOutputString1(@array1)."\n";
print TwoDArrayOutputString2(@array1)."\n"."\n"."\n"."\n";
print TwoDArrayOutputString(@array2)."\n";
print TwoDArrayOutputString1(@array2)."\n";
print TwoDArrayOutputString2(@array2)."\n"."\n"."\n"."\n";
Output:
{{}{}{},}
{{}{}{},}
}
{,}
{,}
}
and my expected output is {{1,2,3},{1,2,3},{1,2,3}}
.
Upvotes: 1
Views: 1093
Reputation: 118118
First off, both of your syntaxes are wrong (compared to what I think you think they do):
my @array1=[[1,2,3],[1,2,3],[1,2,3]];
This results in @array1
holding a single reference to an anonymous array which further holds three references to three anonymous arrays when what I think you want is:
my $array1 = [[1,2,3],[1,2,3],[1,2,3]];
$array1
now is a reference to an array that holds three references to three anonymous arrays.
my @array2=((1,2,3),(1,2,3),(1,2,3));
In this case, you are just fooling yourself with all the extra parentheses: All you have is a single array whose elements are 1, 2, 3, 1, 2, 3, 1, 2, 3
.
You say
now I need to create a subroutine that will return string as {{1,2,3},{1,2,3},{1,2,3}}.
That is an odd requirement. Why exactly do you need to create such a subroutine?
If you want to serialize the array as a string, you'd be better off using one of the more standard and interoperable ways of doing it, and pick a format such as JSON, YAML, XML, Data::Dumper, or something else.
For example:
$ perl -MJSON::MaybeXS=encode_json -E '@array1=([1,2,3],[1,2,3],[1,2,3]); say encode_json \@array1' [[1,2,3],[1,2,3],[1,2,3]]
or
$ perl -MData::Dumper -E '@array1=([1,2,3],[1,2,3],[1,2,3]); say Dumper \@array1' $VAR1 = [ [ 1, 2, 3 ], [ 1, 2, 3 ], [ 1, 2, 3 ] ];
or
$ perl -MYAML::XS -E '@array1=([1,2,3],[1,2,3],[1,2,3]); say Dump \@array1' --- - - 1 - 2 - 3 - - 1 - 2 - 3 - - 1 - 2 - 3
or
$ perl -MXML::Simple -E '@array1=([1,2,3],[1,2,3],[1,2,3]); say XMLout(\@array1)'
<opt>
<anon>
<anon>1</anon>
<anon>2</anon>
<anon>3</anon>
</anon>
<anon>
<anon>1</anon>
<anon>2</anon>
<anon>3</anon>
</anon>
<anon>
<anon>1</anon>
<anon>2</anon>
<anon>3</anon>
</anon>
</opt>
If your purpose is to learn how to traverse a multi-dimensional structure and print it, doing it correctly requires attention to a few details. You could study the source of YAML::Tiny:
sub _dump_array {
my ($self, $array, $indent, $seen) = @_;
if ( $seen->{refaddr($array)}++ ) {
die \"YAML::Tiny does not support circular references";
}
my @lines = ();
foreach my $el ( @$array ) {
my $line = (' ' x $indent) . '-';
my $type = ref $el;
if ( ! $type ) {
$line .= ' ' . $self->_dump_scalar( $el );
push @lines, $line;
} elsif ( $type eq 'ARRAY' ) {
if ( @$el ) {
push @lines, $line;
push @lines, $self->_dump_array( $el, $indent + 1, $seen );
} else {
$line .= ' []';
push @lines, $line;
}
} elsif ( $type eq 'HASH' ) {
if ( keys %$el ) {
push @lines, $line;
push @lines, $self->_dump_hash( $el, $indent + 1, $seen );
} else {
$line .= ' {}';
push @lines, $line;
}
} else {
die \"YAML::Tiny does not support $type references";
}
}
@lines;
}
Now, for your simple case, you could do something like this:
#!/usr/bin/env perl
use feature 'say';
use strict;
use warnings;
my @array = ([1, 2, 3], [4, 5, 6], [7, 8, 9]);
say arrayref_to_string([ map arrayref_to_string($_), @array]);
sub arrayref_to_string { sprintf '{%s}', join(q{,}, @{$_[0]}) }
Output:
{{1,2,3},{4,5,6},{7,8,9}}
Upvotes: 2
Reputation: 3535
One way could be with Data::Dumper
. But correctly pass array
or array-refs
to Dumper
. Your @array2
is one-dimensional array.
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my @array1=[[1,2,3],[1,2,3],[1,2,3]];
my $string = Dumper(@array1);
$string =~ s/\n|\s+|.*?=|;//g;
$string =~ s/\[/\{/g;
$string =~ s/\]/\}/g;
print $string."\n";
output:
{{1,2,3},{1,2,3},{1,2,3}}
Upvotes: 1
Reputation: 21666
You could do something like below:
#!/usr/bin/perl
use strict;
use warnings;
my @array1=[[1,2,3],[1,2,3],[1,2,3]];
foreach my $aref (@array1){
foreach my $inner (@$aref){
print "{";
foreach my $elem (@$inner){
print "$elem";
print ",";
}
print "}";
}
}
PS: I did not understand second array in your example i.e. my @array2=((1,2,3),(1,2,3),(1,2,3));
. It's basically just my @array2=(1,2,3,1,2,3,1,2,3);
.
Upvotes: 1