我试图按照元素各部分的大小对数组进行排序。这些项目遵循模式x/y[.../z]
,我希望它们按照项目数量排序。例如。分割到1/2
后,/
有两项,12/365/85
有三项。我似乎无法弄清楚我在这个看似简单的片段中做错了什么。
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my @dummy_arr = ['12345/3/365/45/12', '1/2', '3/2', '1/2/3', '2/3/4'];
@dummy_arr = sort { scalar ( split /\//, $a ) < scalar ( split /\//, $b ) } @dummy_arr;
print Dumper(\@dummy_arr);
输出:
$VAR1 = [
[
'12345/3/365/45/12',
'1/2',
'3/2',
'1/2/3',
'2/3/4'
]
];
预期产出:
$VAR1 = [
'1/2',
'3/2',
'1/2/3',
'2/3/4',
'12345/3/365/45/12'
];
答案 0 :(得分:11)
你混淆了一些事情。
您将数组引用放入@dummy_arr
。
my @dummy_arr = [ '12345/3/365/45/12', '1/2', '3/2', '1/2/3', '2/3/4' ];
这等于:
my @dummy_arr = ( [ '12345/3/365/45/12', '1/2', '3/2', '1/2/3', '2/3/4' ] );
在Dumper
输出中也可见。
$VAR1 = [ # <-- because of the ref \@dummy_arr you pass to Dumper
[ # <-- first elem is already an array ref
'12345/3/365/45/12',
'1/2',
'3/2',
'1/2/3',
'2/3/4'
]
];
因此,当您执行sort { ... } @dummy_arr
时,只有一个值传递给sort
。因为sort
很聪明,所以它会跳过,因为如果只有$a
但没有$b
则无需排序。当你将{ warn $a; scalar ... }
放入sort
lambda时,这就变得很明显了。没有警告,因此永远不会被召唤。
但是你还是没有排序。 sort
lambda需要返回与-1
,0
或1
类似的内容。
如果指定了SUBNAME,则它会给出子例程的名称 返回小于,等于或大于0的整数,具体取决于 关于如何订购列表的元素。
但您使用的<
只会返回1
或0
。您需要使用<=>
for numerical comparison。
my @dummy_arr = ( '12345/3/365/45/12', '1/2', '3/2', '1/2/3', '2/3/4' );
@dummy_arr = sort { scalar( split /\//, $a ) <=> scalar( split /\//, $b ) }
@dummy_arr;
print Dumper( \@dummy_arr );
__END__
$VAR1 = [
'1/2',
'3/2',
'1/2/3',
'2/3/4',
'12345/3/365/45/12'
];
最后,因为如果数组中有很多元素,拆分是一项昂贵的操作,需要重复很多,你可能想要使用a Schwartzian Transform。< / p>
my @dummy_arr = ( '12345/3/365/45/12', '1/2', '3/2', '1/2/3', '2/3/4' );
@dummy_arr =
map { $_->[0] }
sort { $a->[1] <=> $b->[1] }
map { [ $_, scalar split( qr{/}, $_ ) ] } @dummy_arr;
这会产生相同的输出,但会换掉CPU的内存,因此速度更快。