リストをソートする
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;
}