2

我不太擅长 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
}
4

3 回答 3

5

首先,您应该始终将其放在use strict;程序的顶部。这将及早发现许多错误。

循环中的最后一行是正确foreach取消引用的行。$thingy但是由于您已将(string concatenation) 运算符放在@{$thingy}左侧.,因此数组处于标量上下文中,并且标量上下文中的数组评估为它们的大小。说啊:

print "@{$thingy}\n";

得到@$thingy由空格分隔的元素,或者一般来说

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

如果你想使用另一个分隔符,比如竖线字符。你也可以说

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

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

于 2011-05-23T22:07:35.683 回答
3

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

使用两个嵌套循环

  1. 使用数组引用遍历您的数组
  2. 然后在每个循环中迭代该引用数组中的项目。

像这样

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;
于 2011-05-23T22:14:39.020 回答
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
}
于 2011-05-23T22:34:40.210 回答