1

Letter_Number の組み合わせの配列が与えられた場合、最初に文字で並べ替え、次に数字で並べ替えるにはどうすればよいですか。

( B_5   A_11   C_0   A_10    A_1 )

取得するため:

( A_1   A_10   A_11   B_5    C_0 )

?

4

5 に答える 5

5

デフォルトでは、sort は字句的に比較します。したがって、数値を 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;
}
于 2013-07-11T19:27:06.263 に答える
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;
于 2013-07-11T19:35:17.887 に答える
1

CPAN モジュール Sort::Naturally を試してください。

于 2013-07-11T19:28:06.610 に答える
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;

編集

シュワルツ変換を使用すると、非常に小さな値でも大きな違いが生じます。

#!/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%   --
于 2013-07-11T19:37:31.640 に答える
-2

あなたが探している順序は、すでにソートのデフォルトの動作です...したがって、ソートするだけです:

my @list = qw(B_5 A_11 C_0 A_10 A_1);
my @sorted = sort @list;
于 2013-07-11T19:20:21.153 に答える