首先按字母顺序排序,然后在串联密钥上进行数字排序

时间:2013-07-11 19:12:20

标签: perl sorting

给定一组Letter_Number组合,我如何先按字母排序,然后编号:

( B_5   A_11   C_0   A_10    A_1 )

得到:

( A_1   A_10   A_11   B_5    C_0 )

5 个答案:

答案 0 :(得分:5)

默认情况下,排序以词汇方式进行比较。因此,如果您想将数字视为实际数字,其中010> 1和2< 11,这更像是你需要的东西:

my @list = qw(B_5 A_11 C_0 A_10 A_1);
my @sorted = sort char_then_num @list;

sub char_then_num {
    my ($a_char, $a_num) = split '_', $a;
    my ($b_char, $b_num) = split '_', $b;
    return $a_char cmp $b_char
             ||
        $a_num <=> $b_num;
}

答案 1 :(得分:4)

use Sort::Key::Natural qw( natsort );
my @sorted = natsort @data;

或者如果你想避开模块,

my @sorted =
   map $_->[0],
    sort {  $a->[1] cmp $b->[1] || $a->[2] <=> $b->[2] }
     map [ $_, split /_/ ],
      @data;

答案 2 :(得分:1)

尝试使用CPAN模块Sort :: Naturally。

答案 3 :(得分:1)

简单高效:

my @list = qw(B_5 A_11 C_0 A_10 A_2);

my @sorted = map $_->[0], sort {$a->[1] cmp $b->[1] or $a->[2] <=> $b->[2]} map [$_, split'_'], @list;

修改

使用Schwartzian变换即使对于非常小的值也会产生巨大的差异:

#!/usr/bin/perl

use Benchmark qw( cmpthese );

our $chars = join("","A".."Z");

sub genlist
{
    my $count = shift;
    return map join("_", substr($chars, rand(26),1), int(rand(100))),
        1 .. $count;
}

sub nostcmp {
    my ($a_char, $a_num) = split '_', $a;
    my ($b_char, $b_num) = split '_', $b;
    return $a_char cmp $b_char
             ||
        $a_num <=> $b_num;
}

sub nost {
   return sort nostcmp @_;
}

sub st {
    return
       map $_->[0],
        sort { $a->[1] cmp $b->[1] || $a->[2] <=> $b->[2] }
         map [ $_, split '_' ],
          @_;
}


my %tests = (
   nost => 'my @sorted = nost(@list);',
   st   => 'my @sorted = st(@list);',
);


$_ = 'use strict; use warnings; our @list; ' . $_
   for values %tests;

sub measure
{
    my $count = shift;
    print "Count $count:\n";
    local our @list = genlist($count);
    cmpthese(-3, \%tests);
    print "\n";
}

measure $_ for 5,10,20,50,100;

结果:

Count 5:
         Rate nost   st
nost  82195/s   -- -21%
st   103392/s  26%   --

Count 10:
        Rate nost   st
nost 35430/s   -- -34%
st   53589/s  51%   --

Count 20:
        Rate nost   st
nost 13228/s   -- -48%
st   25277/s  91%   --

Count 50:
       Rate nost   st
nost 4157/s   -- -53%
st   8935/s 115%   --

Count 100:
       Rate nost   st
nost 1637/s   -- -58%
st   3889/s 138%   --

答案 4 :(得分:-2)

您正在寻找的订单已经是排序的默认行为......所以只需排序:

my @list = qw(B_5 A_11 C_0 A_10 A_1);
my @sorted = sort @list;