2015-07-21 3 views
1

С технической точки зрения, в Perl нет многомерных массивов, но вы можете использовать одномерные массивы в Perl, чтобы действовать так, как если бы они имели более одного измерения.В Perl, как я могу укрепить двумерный массив?

В Perl каждый элемент массива может быть ссылкой на другой массив, но синтаксически они будут выглядеть как двумерный массив.

Я хочу преобразовать 2-мерный целочисленный массив в строку в Perl. Я объявил 2-мерный целочисленный массив следующим образом:

my @array1=[[1,2,3],[1,2,3],[1,2,3]]; 

ИЛИ

my @array2=((1,2,3),(1,2,3),(1,2,3)); 

теперь мне нужно создать подпрограмму, которая будет возвращать строку как "{{1,2,3},{1,2,3},{1,2,3}}". Я попробовал следующую подпрограмму:

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"; 

Выход:

{{}{}{},} 
{{}{}{},} 
} 



{,} 
{,} 
} 

и мой ожидаемый выход {{1,2,3},{1,2,3},{1,2,3}}.

ответ

1

Вы могли бы сделать что-то, как показано ниже:

#!/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: Я не понял, второй массив в вашем примере т.е. my @array2=((1,2,3),(1,2,3),(1,2,3));. Это в основном просто my @array2=(1,2,3,1,2,3,1,2,3);.

+0

Да. вы правы @chankey. Можете ли вы проанализировать этот код-aub TwoDArrayOutputString2 { \t my ($ array1) = @_; \t my $ finaloutput = "{"; foreach my $ aref (@ array1) { foreach my $ inner (@ $ aref) { $ finaloutput. = "{"; foreach my $ elem (@ $ inner) { $ finaloutput. = $ Elem. ","; } $ finaloutput. = "}". ","; } } return $ finaloutput; } my @ array1 = [[1,2,3], [1,2,3], [1,2,3]]; print TwoDArrayOutputString2 (\ @ array1); ' –

1

Один из способов может быть с Data::Dumper. Но правильно пройти array или array-refs до Dumper. Ваш @array2 - это одномерный массив.

#!/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"; 

выход:

{{1,2,3},{1,2,3},{1,2,3}} 
2

Во-первых, оба ваших синтаксисах не правы (по сравнению с тем, что я думаю, что вы думаете, что они делают):

my @array1=[[1,2,3],[1,2,3],[1,2,3]]; 

Это приводит к @array1, содержащему отдельную ссылку на аноним s массив, который дополнительно содержит три ссылки на три анонимные массивы, когда то, что я думаю, что вы хотите:

my $array1 = [[1,2,3],[1,2,3],[1,2,3]]; 

$array1 в настоящее время является ссылкой на массив, который содержит три ссылки на три анонимные массивы.

my @array2=((1,2,3),(1,2,3),(1,2,3)); 

В этом случае, вы просто дурачат себя все дополнительные скобки: Все у вас есть один массив, элементами которого являются 1, 2, 3, 1, 2, 3, 1, 2, 3.

Вы говорите

теперь мне нужно создать подпрограмму, которая будет возвращать строку как {{1,2,3}, {1,2,3}, {1,2,3}}.

Это странное требование. Почему именно вам нужно создать такую ​​подпрограмму?

Если вы хотите сериализовать массив в виде строки, вы бы лучше использовать один из более стандартных и совместимых способов сделать это, и выбрать формат, такой как JSON, YAML, XML, Data::Dumper, или что-то остальное.

Например:

$ 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]]

или

$ 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 
      ] 
     ];

или

$ 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

или

$ 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> 

Если ваша цель - научиться перемещаться по многомерной структуре и печатать ее, правильное выполнение этого требует внимания к некоторым деталям. Вы можете изучить источник 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; 
} 

Теперь, для простого случая, вы могли бы сделать что-то вроде этого:

#!/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]}) } 

Выход:

{{1,2,3},{4,5,6},{7,8,9}}
Смежные вопросы