我不是很擅长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
}
答案 0 :(得分:5)
首先,您应该始终将use strict;
放在程序的顶部。那会很早就发现很多错误。
foreach
循环中的最后一行是正确解除引用$thingy
的行。但是,由于您已将@{$thingy}
放在.
(字符串连接)运算符的左侧,因此该数组位于标量上下文中,而标量上下文中的数组将根据其大小进行求值。只是说:
print "@{$thingy}\n";
将@$thingy
的元素用空格分隔,或者通常用
print join('|', @{$thingy}), "\n";
如果要使用其他分隔符,例如竖线字符。你也可以说
print @{$thingy}, "\n";
打印完全没有分隔符的元素。
答案 1 :(得分:3)
@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;
答案 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
}