我似乎无法正确取消引用数组

时间:2011-05-23 21:54:37

标签: arrays perl dereference

我不是很擅长Perl,但我需要能够对多维数组进行排序。我一直在玩一些测试代码,试图更好地掌握这个概念,我想我已经接近了,但我找不到神奇的组合。

我似乎无法做的是取消引用我的数组并让它们正确打印。除了被引用的数组中的值之外,我似乎可以得到关于这些引用的世界上我需要了解的所有内容。

我从制表符分隔的平面文件中获取数据,所以在我的示例代码中,我通过分割创建多个数组然后将它们推入单个数组来模仿它。在实践中,我将循环遍历文件,在选项卡上拆分并在我进入时将它们推入阵列。

如果有更好的方法来解决这个问题,我会全力以赴。平面文件中的每一行都是一条记录。我需要先按日期排序,将最旧的记录放到顶部,然后进行辅助排序,按照帐号对记录进行分组。我在线查看了几个例子,但没有发现任何与我需要模仿的数据相关的东西。

my @s1 = split(/:/, 'X:Y:Z');
my @s2 = split(/:/, 'A:B:C');
my @s3 = split(/:/, 'Q:L:P:0');
my @s4 = split(/:/, 'U:E:G');

my @array = ();
push(@array, \@s1);
push(@array, \@s2);
push(@array, \@s3);
push(@array, \@s4);

print "@array\n";

my @sorted = sort { $a->[0] cmp $b->[0] } @array;

print "\n";
foreach $thingy (@sorted)
{
    print @thingy . "\n"; #result: number 0
    print $thingy . "\n"; #result: reference
    #print ${$thingy} . "\n"; #result: 'Not a scalar reference' error
    print ${@thingy} . "\n"; #result: file name (???)
    print @{$thingy} . "\n"; #result: length of the array referenced
}

3 个答案:

答案 0 :(得分:5)

首先,您应该始终将use strict;放在程序的顶部。那会很早就发现很多错误。

foreach循环中的最后一行是正确解除引用$thingy的行。但是,由于您已将@{$thingy}放在.(字符串连接)运算符的左侧,因此该数组位于标量上下文中,而标量上下文中的数组将根据其大小进行求值。只是说:

print "@{$thingy}\n";

@$thingy的元素用空格分隔,或者通常用

分隔
print join('|', @{$thingy}), "\n";

如果要使用其他分隔符,例如竖线字符。你也可以说

print @{$thingy}, "\n";

打印完全没有分隔符的元素。

答案 1 :(得分:3)

@thingy未声明且未定义(且不必要)。

使用两个嵌套循环

  1. 使用array-references
  2. 遍历数组
  3. 然后在每个循环中迭代该引用数组中的项目。
  4. 喜欢这个

    foreach my $array_ref (@sorted)
    {
        foreach my $item (@{$array_ref}) {
            print $item, ",";
        }
        print "\n";
    }
    

    表达式@{$array_ref}将取消引用您的数组引用。它就像一个数组一样使用。

    增加:

    你可以替换

    my @s1 = split(/:/, 'X:Y:Z');
    my @s2 = split(/:/, 'A:B:C');
    my @s3 = split(/:/, 'Q:L:P:0');
    my @s4 = split(/:/, 'U:E:G');
    
    my @array = ();
    push(@array, \@s1);
    push(@array, \@s2);
    push(@array, \@s3);
    push(@array, \@s4);
    

    my @array = ();
    push(@array, map { [split(/:/, $_)] } qw(X:Y:Z A:B:C Q:L:P:0 U:E:G));
    

    如果排序需要两个标准(第一个索引的主要标准和第二个索引的次要标准),可以这样写:

    my @sorted = sort { $a->[0] cmp $b->[0] 
                                 ||
                        $a->[1] cmp $b->[1] 
                      } @array;
    

答案 2 :(得分:2)

您需要做的第一件事就是将其添加到您的脚本中:

use strict;
use warnings;

然后你会收到警告:

Global symbol "@thingy" requires explicit package name

这意味着未定义@thingy。在perl中,$thingy@thingy计为单独的变量。

创建数组的另一种方法是使用匿名数组,如下所示:

push @array, [ split(/:/, 'X:Y:Z') ];
push @array, [ split(/:/, 'A:B:C') ];
...

然后你不必创建一次性变量。或者使用您描述的文件(\t是标签):

while (<>) {
    push @array, [ split /\t/, $_ ];
}

从perlmonks:

对多列进行排序的方法
my @a = ([1,2], [3,4]);
my @b = sort {

    $a->[0] <=> $b->[0] || # the result is -1,0,1 ...
    $a->[1] <=> $b->[1]    # so [1] when [0] is same

} @a;

http://www.perlmonks.org/index.pl?node_id=674374

当然,这会假设您字段中的数值。否则使用cmp

要打印:

for my $ref (@array) {
    my $i = 0;
    for my $value (@$ref) {
        print $value; 
        print "," if ($i++ < $#$ref); # comma delimited
    }
    print "\n"; # end of record
}