我不太擅长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 "@arrayn";
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
}
首先,您应该始终将use strict;
放在程序的顶部。 这将及早发现许多错误。
foreach
循环中的最后一行是正确取消引用$thingy
的行。 但是,由于您已将@{$thingy}
放在 .
(字符串串联)运算符的左侧,因此数组位于标量上下文中,而标量上下文中的数组的计算值取决于其大小。 只需说:
print "@{$thingy}n";
获取@$thingy
元素用空格分隔,或一般分隔
print join('|', @{$thingy}), "n";
如果要使用其他分隔符,如竖线字符。 你也可以说
print @{$thingy}, "n";
以打印完全不带分隔符的元素。
@thingy
是未声明和未定义的(并且不必要的)。
使用两个嵌套循环来
- 使用数组引用遍历数组
- 然后在每个循环中迭代该引用数组中的项。
喜欢这个
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;
您需要做的第一件事是将其添加到脚本中:
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
}