Perl:正确打印数组数组(取消引用)

时间:2012-06-20 10:07:41

标签: arrays for-loop dereference perl5

嘿同伴perl僧侣,

我仍在围绕如何正确解除引用。 (我在发布之前阅读了类似的帖子,但不幸的是,这个概念仍然有点混乱。)

我有以下数组,内部由两个数组组成。 (顺便说一句,我正在使用严格和警告的pragma。)

use strict; use warnings;
my @a1; my @a2;

其中:

@a1 = ( "1MB", "2MB", ... )

和..

@a2 = ( "/home", "/home/debug", ... )

@ a1& @ a2是包含51行的数组。所以,我将这些填充到我的第二个阵列中。

my @b;
push (@b, [ @a1, @a2 ]);

但是,当我尝试打印@b:

的结果时
sub newl { print "\n"; print "\n"; }
my $an1; my @an1;
$an1 = $#a1;
@an1 = ( 0, 1..$an1 );

for my $i (@an1) { print @b[$i]; &newl; }

我看到了对数组的引用:

ARRAY(0x81c0a10)
  .
ARRAY(0x81c0a50)
  .
  .
  .

如何正确打印此阵列?我知道我需要取消引用数组,我不知道该如何去做。我试着填充我的数组:

push (@b, [ \@a1, \@a2 ]);

产生相同的结果。我也尝试过:

for my $i (@an1) { print @{$b[$i]}; &newl; }

由于将0作为数组引用而导致哪些错误?

Can't use string ("0") as an ARRAY ref while "strict refs" in use at p_disk_ex6.pl line 42.

非常感谢任何建议!

3 个答案:

答案 0 :(得分:1)

一个简短的示例程序,可能会对您有所帮助:

use strict;
use warnings;

my @a1 = qw(1MB 2MB 10MB 7MB);
my @a2 = qw(/foo /bar /flub /blub);

my @b = (\@a1, \@a2);
# equivalent long version:
# my @b = ();
# $b[0] = \@a1;
# $b[1] = \@a2;

for (my $i = 0; $i <= $#a2; $i++) {
    print "a1[$i]: $b[0][$i]\n";
    print "a2[$i]: $b[1][$i]\n";
    print "\n";
}

在你的例子中,你将一个无趣的arrayref []推入@b。因此$ b [0]包含arrayref。

my @b;
push (@b, [ \@a1, \@a2 ]);
# this corresponds to:
# $b[0][0] = \@a1;
# $b[0][1] = \@a2;

在您编写[@ a1,@ a2]的示例中,您创建的array_ref包含连接的数组@ a1和@ a2(首先是@ a1的所有元素,然后是@ a2的所有元素):

my @b;
push(@b , [@a1, @a2]);
# $b[0] = ['1MB' , '2MB', '10Mb', '7MB', '/foo', '/bar', '/flub', '/blub']

答案 1 :(得分:0)

即使只是这也有效

use strict;
use warnings;

my @a1 = qw(1MB 2MB 10MB 7MB);
my @a2 = qw(/foo /bar /flub /blub);

my @b = (@a1, @a2);
print "@b";

答案 2 :(得分:0)

如果你想要一个通用的解决方案,它不假设每个子数组中有多少个元素,并且还允许任意级别的嵌套,那么你最好使用别人已经写过的包。显示递归数据结构。一个特别流行的是YAML,你可以通过运行cpan来安装它:

$ cpan
Terminal does not support AddHistory.

cpan shell -- CPAN exploration and modules installation (v1.9800)
Enter 'h' for help.

cpan[1]> install YAML

然后您可以轻松地显示任意数据结构。用一个简单的例子来演示:

use YAML;

my @a1 = qw(1MB 2MB 10MB 7MB);
my @a2 = qw(/foo /bar /flub /blub);

my @b = (\@a1, \@a2);

print Dump(\@b);

导致输出

---
-
  - 1MB
  - 2MB
  - 10MB
  - 7MB
-
  - /foo
  - /bar
  - /flub
  - /blub

稍微复杂的例子

my @b = (\@a1, \@a2,
         { a => 0, b => 1 } );

给出

---
-
  - 1MB
  - 2MB
  - 10MB
  - 7MB
-
  - /foo
  - /bar
  - /flub
  - /blub
- a: 0
  b: 1

要读取此内容,第1列中的三个“ - ”字符表示包含三个元素的数组。 前两个元素各有四个子元素(第3列中带有“ - ”的行)。该 第三个外部元素是一个哈希引用,因为它由“key:value”对组成。

关于YAML的一个很好的功能是你可以使用它将任何递归数据结构转储到一个文件中,除了那些带有子程序引用的文件,然后使用Load读回它。

如果你真的需要滚动你自己的显示例程,这当然是可能的,但是如果你递归地编写它,你会有一个更容易的时间。您可以使用ref检查您的参数是数组引用还是哈希引用(或标量引用):

my @a1 = qw(1MB 2MB 10MB 7MB);
my @a2 = qw(/foo /bar /flub /blub);

my @b = (\@a1, \@a2,
         { a => 0, b => 1 } );

print_recursive(\@b);
print "\n";

sub print_recursive {
    my ($obj) = @_;

    if (ref($obj) eq 'ARRAY') {
        print "[ ";
        for (my $i=0; $i < @$obj; $i++) {
            print_recursive($obj->[$i]);
            print ", " if $i < $#$obj;
        }
        print " ]";
    }
    elsif (ref($obj) eq 'HASH') {
        print "{ ";
        my @keys = sort keys %$obj;
        for (my $i=0; $i < @keys; $i++) {
            print "$keys[$i] => ";
            print_recursive($obj->{$keys[$i]});
            print ", " if $i < $#keys;
        }
        print " }";
    }
    else {
        print $obj;
    }
}       

产生输出

[ [ 1MB, 2MB, 10MB, 7MB ], [ /foo, /bar, /flub, /blub ], { a => 0, b => 1 } ]

我没有编写我的示例代码来担心漂亮的打印,也没有 处理标量,子例程或有福的对象引用,但它应该让您了解如何编写一个相当通用的递归数据结构转储器。