按拆分大小排序数组

Bra*_*roy 3 sorting perl

我试图按照其元素部分的大小对数组进行排序.这些项目遵循一种模式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);
Run Code Online (Sandbox Code Playgroud)

输出:

$VAR1 = [
          [
            '12345/3/365/45/12',
            '1/2',
            '3/2',
            '1/2/3',
            '2/3/4'
          ]

        ];
Run Code Online (Sandbox Code Playgroud)

预期产量:

$VAR1 = [
            '1/2',
            '3/2',
            '1/2/3',
            '2/3/4',
            '12345/3/365/45/12'
        ];
Run Code Online (Sandbox Code Playgroud)

sim*_*que 11

你混淆了几件事.

你把一个数组引用放入你的@dummy_arr.

my @dummy_arr = [ '12345/3/365/45/12', '1/2', '3/2', '1/2/3', '2/3/4' ];
Run Code Online (Sandbox Code Playgroud)

这相当于:

my @dummy_arr =  ( [ '12345/3/365/45/12', '1/2', '3/2', '1/2/3', '2/3/4' ] );
Run Code Online (Sandbox Code Playgroud)

在您的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'
          ]
        ];
Run Code Online (Sandbox Code Playgroud)

所以当你这样做时sort { ... } @dummy_arr,只传递了一个值sort.因为sort它是聪明的,所以它会跳过,因为没有什么可以排序,如果只有$a,但没有$b.当你把一个{ warn $a; scalar ... }放入sortlambda 时,这就变得很明显了.没有警告,因此它永远不会被调用.

但是你还是没有排序.该sort拉姆达需要返回类似的东西 -1,01.

如果指定了SUBNAME,则它会给出一个子例程的名称,该子例程返回一个小于,等于或大于0的整数,具体取决于列表元素的排序方式.

但你正在使用<,只返回10.您需要使用<=>数字比较.

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'
        ];
Run Code Online (Sandbox Code Playgroud)

最后,因为分裂是一个昂贵的操作需要重复很多,如果有很多数组中的元素,你可能想使用一个使用Schwartzian变换了这一点.

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;
Run Code Online (Sandbox Code Playgroud)

这会产生相同的输出,但会为CPU交换内存,因此速度更快.