在Perl中,我如何对二维数组进行字符串化?

时间:2015-07-21 11:31:49

标签: arrays perl multidimensional-array

从技术上讲,Perl中没有多维数组,但您可以在Perl中使用单维数组,就好像它们有多个维度一样。

在Perl中,数组的每个元素都可以是对另一个数组的引用,但从语法上讲,它们看起来像是一个二维数组。

我想在Perl中将二维整数数组转换为字符串。我已经声明了如下的二维整数数组:

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

OR

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

3 个答案:

答案 0 :(得分:2)

首先,你的两种语法都是错误的(与你认为他们认为的相比):

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

这导致@array1持有对匿名数组的单个引用,当我认为你想要的时候,它进一步保存对三个匿名数组的三个引用:

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}}。

这是一个奇怪的要求。为什么你需要创建这样一个子程序?

如果您想将数组序列化为字符串,最好使用其中一种更标准且可互操作的方式,并选择JSONYAML等格式,XMLData::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}}

答案 1 :(得分:1)

您可以执行以下操作:

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

PS:我不理解你的例子中的第二个数组,即my @array2=(1,2,3,1,2,3,1,2,3);。它基本上只是 private SurfaceView preview=null; private SurfaceHolder previewHolder=null; private Camera camera=null; private boolean inPreview=false; private boolean cameraConfigured=false protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ... preview=(SurfaceView)findViewById(R.id.preview); previewHolder = preview.getHolder(); previewHolder.addCallback(surfaceCallback); previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } private void startPreview() { if (cameraConfigured && camera!=null) { camera.setDisplayOrientation(90); camera.startPreview(); inPreview=true; } } private Camera.Size getBestPreviewSize(int width, int height, Camera.Parameters parameters) { Camera.Size result=null; for (Camera.Size size : parameters.getSupportedPreviewSizes()) { if (size.width<=width && size.height<=height) { if (result == null) { result = size; } else { int resultArea = result.width * result.height; int newArea = size.width * size.height; if (newArea > resultArea) { result = size; } } } } camera.setDisplayOrientation(90); return(result); } private void initPreview(int width, int height) { if (camera!=null && previewHolder.getSurface()!=null) { try { camera.setPreviewDisplay(previewHolder); } catch (Throwable t) { Log.e("Preview-surfaceCallback", "Exception in setPreviewDisplay()", t); Toast .makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_LONG) .show(); } if (!cameraConfigured) { Camera.Parameters parameters=camera.getParameters(); Camera.Size size=getBestPreviewSize(width, height, parameters); if (size!=null) { parameters.setPreviewSize(size.width, size.height); camera.setParameters(parameters); cameraConfigured=true; } } } } SurfaceHolder.Callback surfaceCallback=new SurfaceHolder.Callback() { public void surfaceCreated(SurfaceHolder holder) { // no-op -- wait until surfaceChanged() } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { initPreview(width, height); startPreview(); } public void surfaceDestroyed(SurfaceHolder holder) { // no-op } }; protected void onPause() { if (inPreview) { camera.stopPreview(); } camera.release(); camera=null; inPreview=false; super.onPause(); } protected void onResume() { super.onResume(); camera = Camera.open(); startPreview(); }

答案 2 :(得分:1)

一种方式可能是Data::Dumper。但是正确地将arrayarray-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}}