sort

リストをソートする

構文

解説

sort は、LIST をソートして、そのソートしたリストを返します。

引数 SUBNAME および BLOCK が省略された場合、sort は昇順の文字列ソートを行います。

my @names  = ( 'たろう', 'じろう', 'さぶろう' );
my @sorted = sort @names;
print join( ', ', @sorted );    # さぶろう, じろう, たろう

同じ構文で数値ソートをすると、期待通りの結果になりませんので注意が必要です。

my @nums   = ( 5, 3, 12 );
my @sorted = sort @nums;
print join( ', ', @sorted );    # 12, 3, 5

上記コードの結果を見て分かるように、配列の中の数値は文字列としてソートされてしまいます。 もし数値を期待通りにソートしたいなら、引数 BLOCK に無名サブルーチンをインラインで記述します。

my @nums   = ( 5, 3, 12 );
my @sorted = sort { $a <=> $b } @nums;
print join( ', ', @sorted );    # 3, 5, 12

文字列と数値、昇順と降順

この無名サブルーチンでは、リスト内の比較用の 2 つの要素の値を表すグローバル変数 $a および $b、 そして、比較演算子 cmp または <=> を使って、ソートを定義します。 以下の例は、文字列の昇順ソートと降順ソート、そして、数値の昇順ソートと降順ソートの例を示しています。

# 文字列の昇順ソート
my @sorted1 = sort { $a cmp $b } ( 'たろう', 'じろう', 'さぶろう' );
print join( ', ', @sorted1 ), "\n";    # さぶろう, じろう, たろう

# 文字列の降順ソート
my @sorted2 = sort { $b cmp $a } ( 'たろう', 'じろう', 'さぶろう' );
print join( ', ', @sorted2 ), "\n";    # たろう, じろう, さぶろう

# 数値の昇順ソート
my @sorted3 = sort { $a <=> $b } ( 5, 3, 12 );
print join( ', ', @sorted3 ), "\n";    # 3, 5, 12

# 数値の降順ソート
my @sorted4 = sort { $b <=> $a } ( 5, 3, 12 );
print join( ', ', @sorted4 ), "\n";    # 12, 5, 3

無名サブルーチンを指定しない構文は文字列の昇順ソートですので、以下の 2 つのコードは同じソートを行います。

my @sorted = sort @names;
my @sorted = sort { $a cmp $b } @names;

連想配列の値でソート

配列の中に収められている各要素が連想配列とします。その連想配列の特定のキーの値でソートするには次のように記述します。

my @family = (
    { name => "太郎",  age => 33 },
    { name => "小次郎", age => 5 },
    { name => "花子",  age => 31 }
);

my @sorted = sort { $a->{age} <=> $b->{age} } @family;

for my $person (@sorted) {
    print $person->{name} . "(" . $person->{age} . ")\n";
}

上記コードは、次のような結果を出力します。

小次郎(5)
花子(31)
太郎(33)

名前付きサブルーチンで複雑なソートを行う

これまでソートのアルゴリズムを無名サブルーチンとして sort の引数にインラインで記述しましたが、 インラインでは複雑なソートアルゴリズムを記述できません。 その場合は、名前付きのサブルーチンとしてソートアルゴリズムを記述して、 sort にはそのサブルーチンの名前を指定することもできます。

my @sorted = sort sortalgo @names;

sub sortalgo {
    return $a cmp $b;
}