按拆分大小排序数组

时间:2017-03-01 09:55:45

标签: perl sorting

我试图按照元素各部分的大小对数组进行排序。这些项目遵循模式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'
        ];

1 个答案:

答案 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需要返回与-101类似的内容。

  

如果指定了SUBNAME,则它会给出子例程的名称   返回小于,等于或大于0的整数,具体取决于   关于如何订购列表的元素。

但您使用的<只会返回10。您需要使用<=> 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的内存,因此速度更快。